| |
|
|
Uwe ''Pascal'' Niemeier | Hi Leute (insbesondere Roland)!
Das Subject sagts ja schon: Kann man eine SubClassProc per Return verlassen und dabei Werte zurückgeben?? Zumindest, wenn man vorher Set(WinProc,0) einsetzt?
Die Aiuto ist da nicht sehr informativ
BTW: Wann genau müssen Set(WinProc,n) und Set(SubClassMode,n) überhaupt angewendet werden? Von den Set-Funktionen bin ich es gewohnt, daß diese mehr oder weniger globale Einstellungen vornehmen und meist am Anfang des Programmi stehen...
Ich knabbere nämlich immer noch am CUSTOMDRAW per diverse Controls...
...more data necessary... Pascal |
|
|
| |
|
|
|
| Wäre einfacher wenn man per return 0 oder 1, WinProc 0 oder 1, setzen potuto - wie es normalerweise so (fast) auch ist.
CustomDraw/OwnerDraw mit XProfan11 per SubClassProc wird leider nicht korrekt funktionieren können, weil im seltensten Fall Anweisungen die ein Neuzeichnen auslösen, in der SubClassProc (also im WaitInput) ausgelöst werden, sondern eben ausserhalb waitInput - wo jedoch die Zeichnungsmessages verloren gehen.
Beispiel:
Braucht mal solch eine Message etwas länger und kann nicht sofort vom XProfan-Prozess aufgenommen werden - erreicht sie tatsächlich (aber nur unsicher und von Sys zu Sys anders je nach Performance) das waitInput und damit die SubClassproc - um zu (Owner)-Zeichnen.
Ich fürchte damit, dass solange Roland kein gestacktes ProcAddr bastelt, alle diese Probleme bestehen bleiben. Um so erfreulicher aber ists wiederum, dass imho damit nur durch das Fixen des ProcAddr-Problemes auch die gestackten UserMessages und die SubClassProc unnötig werden und es dann auch kein gefährliches Subclassing mehr gibt.
AddString in der SubClassProc aufrufen oder das ganze Programm nur in der SubClassProc ausführen hat wieder andere Nachteile, wobei das auch Sinnfrei ist solange kein Stack...
Bitmap(-Controls)s potuto man nehmen, ich glaube ich mache das so in der knobcontrol.inc.
Übrigens, dass was ich Stack nenne kann leider kein einfacher Stack sein, weil eigentlich garnichts gestackt werden kann, z.B. Adressen von Speichern welche als Rückgabewert dienten welche bei späterem Abruf (wg. Stack) sicherlich garnicht mehr vorhanden sein müssen.
Unter folgender Konstellation wäre es vielleicht Möglich, dem Problem der Runtime-Synchonisation auf die Schliche zu kommen - wobei ich davon ausgehe, dass eine Umsetzung auf XProfan einen gewissen Aufwandt bedeutet:
Thread1, welcher die Messages empfängt, darf nicht der Thread sein, der den Quellcode interpretiert und ausführt.
Somit kann Thread1 warten, bis Thread 2 an Stelle X ist (subClassProc bzw. procaddr-Bereit), Stelle X ausführen und Thread 1 nur die Rückgabe zurückliefern. Thread 1 wartet dann solange, und alle Programme welche Thread 1 eine Nachricht gesandt haben eben auch - wie es sonst ja normalerweise auch in der Windowswelt von Statten geht.
Eine Idee, selbst Thread1 bereitzustellen und die Runtime sozusagen nachzuladen in Thread2 ist gescheitert, da ich nicht meinen Thread1 mit dem (danach) Runtime-Thread2 synchonisieren konnte, weil ich keine vom XProfan-Code dafür bereitgestellten Mutexe o.Ä. auffinden konnte. |
|
|
| |
|
|
|
RGH | Ciao,
ich will mal versuchen, es etwas besser als in der Aiuto zu erläutern:
Set(WinProc, N%) (N = 0 oder 1)
Jedes Fensterin Windows hat eine Fensterprozedur, die per das Bearbeiten aller Messages zuständig ist, die an das Fenster geschickt werden. Diese wird in der Regel mitder jeweiligen Fensterklasse festgelegt. Normalerweise gibt es per die meisten Windows-Messages eine windowseigene Standardbehandlung. Diese sorgt zum Beispiel beim Drücken der Tab-Taste dafür, dass der Focus ins nächste Dialogelement geht, ohne dass man es eigens in der zugehörigen Windowsprozedur programmieren müsste. Andere Messages werden allerdings in der Fensterprozedur behandelt. Der Normalfall ist also, dass per alle Messages, die nicht in der Fensterprozedur behandelt werden, die Standardbehandlung aufgerufen wird.
Mit Subclassing wird nun die ursprüngliche Windowsprozedur durch unsere eigene Windowsprozedur ersetzt. Anstelle der per die Fensterklasse definierte Fensterprozedur wird nun unsere Prozedur aufgerufen. In der Regel verwenden wir Subclassing aber nur, um einige spezielle Messages einer Spezialbehandlung zu unterziehen und der Rest soll eigentlich so funktionieren wie gewohnt. Hier kommt Set(WinProc,...) ins Spiel: Wenn WinProc beim Verlassen der SubProc auf 1 steht, wird anschließend die ursprüngliche Windowsprozedur aufgerufen, anderenfalls eben nicht. Im Normalfall wird man WinProc dann auf 0 setzen, wenn die Message in der SubClassProc behandelt wurde, ansonsten eben auf 1. (In einigen Fällen kann es jedoch auch Sinn machen auch bei Reaktion auf die Message trotzdem noch die Windowsprozedur per diese Message aufzurufen. Daher kann der Programmierer das mit der Set-Funktion frei bestimmen.)
Return in SubClassProc Ja, Return kann (und muss in einigen Fällen) verwandt werden. Return bestimmt den Rückgabewert der Message. Bei den meisten Messages, die an ein Fenster geschickt werden, spielt der Rückgabewert keine Rolle, bei einigen aber eine ganz erhebliche! Das ist dann der Aiuto zur jeweiligen Message zu entnehmen, etwa wenn circa eine Message angefragt wird, ob das Fenster geschlossen werden kann. Ein Returnwert macht aber nur dann Sinn, wenn WinProc auf 0 steht, da ja andernfalls die anschließend aufgerufene Original Fensterprozedur den Rückgabewert bestimmt.
Saluto Roland |
|
|
| Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD - ATI Radeon HD 4770 512 MB - Windows 7 Home Premium 32Bit - XProfan X4 | 06.03.2009 ▲ |
|
|
|
|
Uwe ''Pascal'' Niemeier | Hi Leute!
@ iF:
Wäre einfacher wenn man per return 0 oder 1, WinProc 0 oder 1, setzen potuto - wie es normalerweise so (fast) auch ist.
Zumindest wären entsprechende spezielle Rücksprungbefehle von der Syntax her einleuchtender gewesen...
CustomDraw/OwnerDraw mit XProfan11 per SubClassProc wird leider nicht korrekt funktionieren können, weil im seltensten Fall Anweisungen die ein Neuzeichnen auslösen, in der SubClassProc (also im WaitInput) ausgelöst werden, sondern eben ausserhalb waitInput - wo jedoch die Zeichnungsmessages verloren gehen.
Darum ja mein Vorschlag, das ProcAddr-Verhalten als SubClass-Modus einzuführen
Wobei ich - wie du weißt - nicht der Meinung bin, SubClassing per ProcAddr wäre gefährlich (bestenfalls während der Entwicklung, wenn man noch nicht genau weiß, was man tut). Einige Programme von mir nutzen dies bis zum Exzess (selbst per meine Maßstäbe!) und sind seit Jahren im täglichen Dauereinsatz. Mich ärgert nur, daß XProfan 11 sowas grundsätzlich eingebaut hat und ich es nicht zum Laufen kriege...
@ Roland:
Ein Returnwert macht aber nur dann Sinn, wenn WinProc auf 0 steht, da ja andernfalls die anschließend aufgerufene Original Fensterprozedur den Rückgabewert bestimmt.
So dachte ich mir das.
In meinem Fall sollte es so sein, daß eine bestimmte Rückgabe Windows veranlaßt, die Proc erneut mit modifizierten Parametern aufzurufen, was aber anscheinend nicht der Fall ist...
Alt mit ProccAddr:
window 10,10-500,500
$H Messages.ph
$H Windows.ph
$H commctrl.ph
var Lv&=create(gridbox,%hwnd,Test;0;150,0,200,10,200,200)
addstring(Lv&,Test1)
addstring(Lv&,Test2)
declare LvDraw#
struct LvDraw= HwndFrom&,idFrom&,Code&,DrawStage&,Rest#(44)
dim LvDraw#,LvDraw
proc LvProc--------------------------------------------------------
parameters wnd&,msg&,wparam&,lparam&
if msg&=~WM_NOTIFY
LvDraw#=lparam&
if LvDraw#.Hwndfrom&=Lv&
if LvDraw#.Code&=~NM_CUSTOMDRAW
if LvDraw#.DrawStage& = ~CDDS_PREPAINT
print PREPAINT erkannt
return ~CDRF_NOTIFYITEMDRAW
elseif LvDraw#.DrawStage& = ~CDDS_ITEMPREPAINT
print ITEMPREPAINT erkannt
endif
endif
endif
endif
return ~DefWindowProc(wnd&,msg&,wparam&,lparam&)
endproc-------------------------------------------------------------
set(fastmode,1)
~SetWindowLong(%hwnd,~GWL_WNDPROC,procaddr(LvProc,4) )
while 1
waitinput
endwhile
Neu mit SubClass:
window 10,10-500,500
$H Messages.ph
$H Windows.ph
$H commctrl.ph
var Lv&=create(gridbox,%hwnd,Test;0;150,0,200,10,200,200)
addstring(Lv&,Test1)
addstring(Lv&,Test2)
declare LvDraw#
struct LvDraw= HwndFrom&,idFrom&,Code&,DrawStage&,Rest#(44)
dim LvDraw#,LvDraw
subclassproc--------------------------------------------------------
if %smessage=~WM_NOTIFY
LvDraw#=&slparam
if LvDraw#.Hwndfrom&=Lv&
if LvDraw#.Code&=~NM_CUSTOMDRAW
if LvDraw#.DrawStage& = ~CDDS_PREPAINT
print PREPAINT erkannt
set(subclassmode,1)--???
set(winproc,0)-------???
return ~CDRF_NOTIFYITEMDRAW
elseif LvDraw#.DrawStage& = ~CDDS_ITEMPREPAINT
print ITEMPREPAINT erkannt--Hier kommt nichts mehr an!
endif
endif
endif
endif
endproc-------------------------------------------------------------
SubClass %hwnd,1
while 1
waitinput
endwhile
Vielleicht sehe ich auch nur den Wald vor lauter Bäumen nicht?
SeeYou Pascal |
|
|
| |
|
|
|
RGH | Uwe Pascal Niemeier
Vielleicht sehe ich auch nur den Wald vor lauter Bäumen nicht?
... ähem ... da lag tatsächlich ein Bug vor, der den Rückgabewert verhinderte ... Das RETURN bleibt in SUBCLASSPROC wirkungslos.
Sorry! Ich sehe schon, der nächste Bugfix kommt bestimmt. Es wird wohl bald ein XProfan 11.2 geben.
Saluto Roland |
|
|
| Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD - ATI Radeon HD 4770 512 MB - Windows 7 Home Premium 32Bit - XProfan X4 | 07.03.2009 ▲ |
|
|
|
|
Jac de Lad | Wird da eventuell auch das andere hier angesprochene mit angepasst? |
|
|
| Profan² 2.6 bis XProfan 11.1+XPSE+XPIA+XPRR (und irgendwann XIDE) Core2Duo E8500/T2250, 8192/1024 MB, Radeon HD4850/Radeon XPress 1250, Vista64/XP | 07.03.2009 ▲ |
|
|
|
|
RGH | Jac
Wird da eventuell auch das andere hier angesprochene mit angepasst?
Was genau meinst Du damit? |
|
|
| Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD - ATI Radeon HD 4770 512 MB - Windows 7 Home Premium 32Bit - XProfan X4 | 07.03.2009 ▲ |
|
|
|
|
Jac de Lad | Subclassing außerhalb von Waitinput und das mit ProcAddr. |
|
|
| Profan² 2.6 bis XProfan 11.1+XPSE+XPIA+XPRR (und irgendwann XIDE) Core2Duo E8500/T2250, 8192/1024 MB, Radeon HD4850/Radeon XPress 1250, Vista64/XP | 08.03.2009 ▲ |
|
|
|
|
| Uwe Pascal Niemeier
Wobei ich - wie du weißt - nicht der Meinung bin, SubClassing per ProcAddr wäre gefährlich (bestenfalls während der Entwicklung, wenn man noch nicht genau weiß, was man tut).
Einige Programme von mir nutzen dies bis zum Exzess (selbst per meine Maßstäbe!) und sind seit Jahren im täglichen Dauereinsatz.
Ok hör mal, per gefährlich halte ich es nicht gerne denn es blockiert mich ganz erheblich weshalb ich seither um Stack bettle.
Nur theoretisch per gefährlich hielt ich es Anfangs als ich versuchte mir vorzustellen wie das gelöst wurde, bzw. weil hier und da immer mal eine kleine Info kam wie es denn gelöst sei.
Leider hat sich nicht nur in einfachsten Tests herausgestellt (ich glaube wir hatten das schon handfest), dass tatsächlich bei einem Aufruf einer mit ProcAddr-bezogenen Funktion, wenn XProfan z.B. sich nicht im WaitInput è, es ganz einfach und nicht nur bei mir garnicht selten knallt.
Die Fehler kommen dann immer wie aus der Luft und sind selten nachvollziehbar bzw. beziehbar auf das ProcAddr-Problem.
Nach (dann doch jahrelangem) (hartnäckigen) nachkratzen hatte Roland - meiner Ansicht nach - das Problem auch bestätigt und verwiesen das eben eine mit ProcAddr-bezogene Funktion per z.B. ENum-Apis gedacht ist - also wenn XProfan steht bzw. wartet oder sich eben im WaitInput è.
Tatsächlich musste ich enorm viel umschreiben an Software damit eben keine unerklärlichen Abstürze mehr passieren - seither mein StackGebettel.
Auuuch wenn z.B. ein Programm das ProcAddr auf gefährliche Weise nutzt, dann è das längst nicht, dass es immer knallt. Die Sache ist imho sogar so komplex, dass man sagen kann, dass es Systeme gibt auf denen es dann ständig knallt und es Systeme gibt, bei denen es so gut wie nie Knallt.
Beide Systeme habe ich hier in Vorhaltung weshalb ich ums ver** kein ProcAddr gefährlich nutze weil mir unerklärliche Abstürze horrend viel Zeit und Nerven gekostet hatten - und wer baut schon gern auf Zuckerstäben*.
*) ausgenommmen (naturalmente) die Fraggles
Was ich nicht so dolle finde ist, dass Roland - weil gefährliches procAddr nunmal nicht immer abstürzt - nicht klar sagt, dass er von der Nutzung von ProcAddr abraten würde ausgenommen per den gedachten Fall der EnumApis bzw. wenn XProfan steht. Jedenfalls potuto ich mir dann viel Gesabbel ersparen was imho keiner (mehr) hören will; mag; muss; kann; brauch.
Um es bildlich zu machen stellt Roland imho z.B. folgendes nicht sicher:
|MARKE|Print 1+5+meineFunktion()+5+2 |MARKE|andereFunktion(solala)*primadoll
Würde die angecallte Funktion z.B. nur bei |MARKE| Ausführung erlangen, wäre das Problem deutlich schmächtiger.
Im aktuellen Fall kann die gecallte Funktion imho aber mitten im 1+5+hier oder mitten in meineFunktion(hier)+5 oder sonst mittendrin corsa werden, was naturalmente, wenn man es sich vorstellt, garnicht ungefährlich sein muss - bedenke man z.B. eine delTree-Funktion welche auf einmal ein Call verpasst bekommt woraufhin sich dann irgendwas ändert. : - /
Natürlich kann hier jede Detailinfo von der Wirklichkeit - die wohl nur Roland kennen mag - abweichen, naturalmente sind das lediglich meine Beurteilungen die Roland (bitte!) in der Luft zerfetzt per falsch deklariert. |
|
|
| |
|
|
|
Jac de Lad | Mein unqualifizierter Kommentar:
Liegt es nicht daran, dass mehrere Procs dann gleichzeitig versuchen auf gleiche Sachen, z.B. Variablen zuzugreifen? Das würde erklären, warum ich nie Probleme mit ProcAddr() hatte (SetTimer und so), weil ich das meist nur benutze, um in der Statuszeile die Uhrzeit und z.B. den Speicherverbrauch anzugeben, das kommt eben nicht mit anderen Funktionen ins Gehege. |
|
|
| Profan² 2.6 bis XProfan 11.1+XPSE+XPIA+XPRR (und irgendwann XIDE) Core2Duo E8500/T2250, 8192/1024 MB, Radeon HD4850/Radeon XPress 1250, Vista64/XP | 09.03.2009 ▲ |
|
|
|
|
| Desto weniger abgearbeitet werden muss... aber imho ist selbst ein return in Zeile 1 der Proc gefährlich.
Nachtrag: Ist wohl Wurstbrot wieviel abgearbeitet wird, Daufruf selbst ist imho eher das Problem. |
|
|
| |
|
|
|
| Hier ein Beispiel welches bei egal welchem WhileLoop-Parameter nicht zucken potrebbe wenn es denn geregelt wäre.
Der anhängige Screenshot zeigt, dass nicht jede Zeile beschrieben wird.
Aufgrund der Tatsache, dass naturalmente 10ms vergleichbar Jahrzehnte sind, entsteht der Fehler nur relativ selten.
Dreht man den WhileLoop-Parameter etwas höher vlt. sogar bis zum Exzess, so wird die Anwendung immer Lustiger reagieren bis zu lustigen Abstürzen...
Naja, fehlt der Zeilenumbruch... liegt halt am Print ist nicht meine Einstellung. |
|
|
| |
|
|