Ownerdrawing - Frage an die GRA-Profis

Grafische Primitive, XbaseParts und Darstellungsfragen allgemein.

Moderator: Moderatoren

Antworten
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9367
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 102 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Ownerdrawing - Frage an die GRA-Profis

Beitrag von Tom »

Ich habe ein sehr umfangreiches, extrem flexibles und wirklich erstaunliches Control gebaut. Letztlich handelt es sich um ein Calendar-Control, zugleich aber um weit mehr als das. Es basiert prinzipiell auf einem simplen Static, das auch das einzige Basisobjekt ist. Das hat verschiedene Gründe - ich hatte überlegt, aus allen Elementen einzelne Objekte zu machen, aber so, wie ich es schließlich umgesetzt habe, ist es weitaus eleganter und im Handling viel einfacher. Es gestattet Millionen Dinge, Paralleldatenanzeige, jede Menge Skalierungen usw. usf.

Die gesamte Logik dieses Controls liegt in einerseits in der Draw-Routine und andererseits im Handler. Das funktioniert auch prima, selbst unter wildesten Bedingungen, eingebettet usw. usf.

Ich habe nun nur noch ein kleines Problem, das aber leider ein unschönes ist. Bei jeder Interaktion muss das Control neu gezeichnet werden, nebst Hintergrund, der auch nicht statisch ist, sondern sich einerseits bewegen kann und andererseits skalierbar ist. Ich habe zwar schon intensiv mit GraPathClip() herumgefrickelt, um den neu zu zeichnenden Bereich einzuschränken (funktioniert auch), wobei ich festgestellt habe, dass GraPathClip() offenbar - entgegen der Dokumentation - keine verschachtelten Clipping-Areas gestattet, aber das tut hier nichts zur Sache. Verschiebe ich jetzt beispielsweise ein "Objekt" (also einen Termin - der überhaupt kein Objekt ist), gibt es ein kurzes Flackern. Mit GraPathClip() kann ich immerhin den Bereich einschränken, der flackert, nichtsdestotrotz bleibt es dabei. Sehr kurz, nicht wirklich unbequem, auf schnellen Rechnern mit schnellen Grafikkarten kaum zu bemerken - aber eben vorhanden. Das Problem: Ich MUSS den Hintergrund fast immer neu zeichnen.

Also. Gibt es irgendeinen Kniff, um das zu umgehen? Und kommt mir bitte nicht mit LockUpdate() oder so - das verhindert das Zeichnen grundsätzlich; der Bildschirm bleibt also leer. Unbrauchbar. :wink: Oder mit dem Hinweis, daraus zwei Objekte zu machen. Das geht (und flackert dann auch nicht), ist aber ebenfalls nicht verwendbar. Weil der Hintergrund eben nicht statisch ist.

Ach so, ergänzender Hinweis: Nicht das gesamte Control flackert, sondern nur der Bereich, der mehrfach gezeichnet wird, weil zuerst der Hintergrund und einige andere Elemente (eben auch teilweise, mit GraPathClip()), und dann die Daten gemalt werden. Die Daten sind also kurz - sehr kurz - unsichtbar und dann doch wieder. Darum geht es mir. Das Neuzeichnen des Hintergrunds sieht man nicht; das habe ich bereits hinbekommen.
Herzlich,
Tom
Benutzeravatar
azzo
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 483
Registriert: So, 28. Mär 2010 19:21
Danksagung erhalten: 11 Mal

Re: Ownerdrawing - Frage an die GRA-Profis

Beitrag von azzo »

Hallo Tom,
kannst du ::nStyle selbst setzen.

::nStyle = nOr( WS_CHILD, WS_VISIBLE, WS_TABSTOP, WS_BORDER, WS_CLIPCHILDREN )
mfg
Otto
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12909
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 46 Mal

Re: Ownerdrawing - Frage an die GRA-Profis

Beitrag von AUGE_OHR »

hi,

das "Problem" ist Ownerdraw vs. Customdraw ... mit einem Browse was es nicht als Windows Control gibt.

bei einem "echten" Windows Customdraw wird nur "die" Cell manipuliert die wir beeinflussen wollen und das OS() macht den Rest
bei Ownerdraw wird nun leider das "ganze" Bild gezeichnet ... mit visual Style denn "das" ist IMHO dass was man "flackern" sieht.

nun wollen wir ja bei Ownerdraw die Kontrolle selbst haben, also "könnte" man ja den visual Style "ersetzten" ... oder ganz abschalten
mit "ersetzten" meine ich nun ein "Hintergrundbild" in einem XbpBrowse ... das hab ich auf der Devcon gezeigt und ich finde das es nicht mehr "flackert"
gruss by OHR
Jimmy
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9367
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 102 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: Ownerdrawing - Frage an die GRA-Profis

Beitrag von Tom »

Es geht nicht um ein Browse. Visuelle Stile sind hier völlig unerheblich. Das Control basiert auf einem (leeren) Textstatic, sieht immer gleich aus, ganz egal, ob visuelle Stile aktiv sind oder nicht, und alles, was sich darauf befindet, zeichne ich selbst. Alles. Um mal einen kleinen Eindruck zu bekommen - einfaches Beispiel im Anhang. Dort sieht man z.B. einen aktiv markierten Termin (10.00 bis 11.30 am Montag), den könnte man jetzt in alle Richtungen verschieben, verlängern, verkürzen u.v.a.m, mit der Maus oder mit der Tastatur. Dieser Termin ist kein Objekt. Macht man also jetzt etwas mit diesem Termin, müssen der Hintergrund, aber auch etwaige überlappende Termine neu gezeichnet werden. Hierfür wird mit GraPathClip() bereits der Bereich eingegrenzt, der neu gezeichnet wird, nämlich nur der betroffene (alle Termine im jeweiligen Bereich, außerdem - und das ist das Problem - natürlich auch der Hintergrund). Der Hintergrund ist nicht statisch, man kann das ganze scrollen, aber z.B. auch mit Shift-Mausrad die Skalierung ändern, also die Größe der Zeitabschnitte.

Was ich also - lediglich - suche, ist irgendein GRA-Trick. Ich zeichne nämlich erst den Hintergrund für den betroffenen Bereich neu, und danach die Termine, die dadurch ganz kurz nicht zu sehen sind - und es flackert eben. Das ist nur ein kosmetisches Problem, aber es stört eben. Ich habe mich durch sämtliche GRA-Funktionen gewühlt und bislang nichts gefunden. Am liebsten wäre es mir, wenn man das Control erst nach dem Neuzeichnen sehen könnte, aber das geht ja nicht - oder doch?
Dateianhänge
cal.jpg
cal.jpg (538.71 KiB) 5258 mal betrachtet
Herzlich,
Tom
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16517
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Re: Ownerdrawing - Frage an die GRA-Profis

Beitrag von Martin Altmann »

Moin,
Du nutzt doch den MicroPS - also :lockPS(), "malen" und :unlockPS() - oder?

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Ownerdrawing - Frage an die GRA-Profis

Beitrag von brandelh »

Im Prinzip müsstest du aus dem Hintergrund die Bereiche herausclippen, die einen Vordergrund haben,
bei einem Fenster wäre das ClipCildren ... aber wie du schreibst, hast du schon alle "Eingrenzungen" auf betroffene Bereiche eingestellt ...
Ich fürchte, mit Xbase++ ist nicht mehr möglich, besser würde es mit mehr Geschwindigkeit beim Refresh aussehen, aber die haben wir nicht.
Auch meine mit Fenster mit TOP LEFT flackern etwas wenn ich den Bereich nach unten erweitere, Xbase++ ist im Bildaufbau einfach nicht schnell genug.

PS: ich lass mir gerne beweisen dass ich Unrecht habe ;-)
Gruß
Hubert
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9367
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 102 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: Ownerdrawing - Frage an die GRA-Profis

Beitrag von Tom »

@Martin: LockPS() und UnlockPS() sind wirkungslos. Man sieht das Zeichnen dennoch.

@Hubert: Das mache ich im Prinzip ja schon. Letztlich müsste ich wahrscheinlich die Überschneidungsbereiche ermitteln und mit einer Mischzeichenoperation doppelt zeichnen, also quasi "Negative" drüberlegen, nehme ich an. Das Problem ist die Vielfalt der möglichen Überschneidungen - das ist eine Rechenoperation, die im Nirvana landet. Ich hatte darauf gehofft, dass jemand von Euch einen einfacheren Trick kennt. Übrigens flackert es auf einem äußerst schnellen Rechner mit rasanter Grafikkarte fast überhaupt nicht. Nur haben die wenigsten solche Hardware.
Herzlich,
Tom
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12909
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 46 Mal

Re: Ownerdrawing - Frage an die GRA-Profis

Beitrag von AUGE_OHR »

hi,

ich sehe im Snapshot am Mo. zwischen 10:00 - 11:30 ein Textfeld mit runden Ecken ...

Frage : geht es um das "bewegen" oder nach einem "drop" um das "neuzeichnen" wo es flackert ?

wenn es um das "bewegen" geht könntest du ja mal meinen Devcon Ownerdraw Demo ausprobieren ;)
gruss by OHR
Jimmy
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Ownerdrawing - Frage an die GRA-Profis

Beitrag von brandelh »

Hallo Tom,
hast du mal daran gedacht 2 Ebenen (Zeichenflächen) zu verwenden ?
Hauptfenster refresh sperren, auf einem unsichtbaren zeichnen und dann den Bereich grafisch kopieren ?
Gruß
Hubert
UliTs
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2828
Registriert: Fr, 10. Feb 2006 9:51
Wohnort: Aachen
Hat sich bedankt: 259 Mal
Danksagung erhalten: 12 Mal
Kontaktdaten:

Re: Ownerdrawing - Frage an die GRA-Profis

Beitrag von UliTs »

Hallo Tom,

blöde Frage: kann man vielleicht auf den "Hintergrund" ganz verzichten, indem Du zu unterst ein "Objekt" legst mit maximaler Größe :?:
Dann ist nirgends mehr der Hintergrund zu sehen und Du "mußt" ihn nie zeichnen :D
Der optische Hintergrund des Controls ist dann in Wirklichkeit der Vordergrund dieses "Objektes" 8)

Uli
-------
Mitglied XuG Cologne
Mitglied XuG Osnabrück
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12909
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 46 Mal

Re: Ownerdrawing - Frage an die GRA-Profis

Beitrag von AUGE_OHR »

azzo hat geschrieben:kannst du ::nStyle selbst setzen.
::nStyle = nOr( WS_CHILD, WS_VISIBLE, WS_TABSTOP, WS_BORDER, WS_CLIPCHILDREN )
nein das können wir unter Xbase++ "nicht so einfach" ...
WS_CLIPCHILDREN wäre wohl die Lösung*** aber dazu müsste man, NACH dem o:create(), den GWL_STYLE ändern.

man kann ja mal die XbParts testen mit

Code: Alles auswählen

   nStyle  := @user32:GetWindowLongA(hWnd , GWL_STYLE)
***
http://msdn.microsoft.com/en-us/library ... 85%29.aspx
An application can prevent a child window's update region from being set when the parent window's is set by specifying the WS_CLIPCHILDREN style when creating the parent window. When this style is set, the system excludes the child windows from the parent's visible region and therefore ignores any portion of the update region that may contain the child windows. When the application paints in the parent window, any drawing that would cover the child window is clipped, making a subsequent WM_PAINT message to the child window unnecessary.
... hm ... man könnte, per SubClassing, versuchen die WM_PAINT Message "abzufangen" wenn man "in Aktion" ist ...
gruss by OHR
Jimmy
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Ownerdrawing - Frage an die GRA-Profis

Beitrag von brandelh »

Hi,

ich denke wenn man den autorefresh abschaltet - XBP_INVREGION_LOCK - und eine Kombination von mehreren :invalidateRect() mit dem 4. Parameter nutzt, sollte man den "neu zeichnen Bereich" stark eingrenzen können. Erst sperren, dann bisherige "Vordergrundbereiche" als ungültig markieren, dann den aktuellen Vordergrundbereich aussparen, nun den Hintergrund anzeigen lassen und dann den Vordergrund malen (das müsste ohne Verrenkungen gehen, da ja dieser Bereich ausgespart wurde) ...
Gruß
Hubert
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Ownerdrawing - Frage an die GRA-Profis

Beitrag von brandelh »

Ich habe vor einigen Jahren mit den GraFunktionen eine Uhr gemacht.
Der Zeiger muss über den Hintergrund und z.B. die Datumsanzeige.
Entscheident ist einerseits der MIXMODE beim Malen (Linie überschreibt den Hintergrund, spart aber kein Viereck aus)
und andererseits die Eingrenzung auf den absolut kleinsten :invalidRect() Bereich.
Ich komme mit einem aus, du musst wahrscheinlich mehrere kombinieren und dann auf einmal auslösen.

Ich hänge das Beispiel mal an, wobei ich fürchte, dass du das schon alles weißt. Du bist ja der OwnerDraw Profi ;-)
Dateianhänge
HB_CLOCK_1.02.ZIP
(560.37 KiB) 181-mal heruntergeladen
Gruß
Hubert
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9367
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 102 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: Ownerdrawing - Frage an die GRA-Profis

Beitrag von Tom »

Hallo, Ulli.

Der Hintergrund ist nicht statisch. Man kann jederzeit seine optischen Parameter verändern, er enthält dynamische "Sperrbereiche" (z.B. außerhalb der Schichtzeiten von Mitarbeitern, sieht man im Beispiel schraffiert), vor allem aber ist er scroll- und skalierbar (!). Deshalb hat es keinen Sinn, wie von Dir vorgeschlagen vorzugehen. Ich hatte auch schon zwei Objekte übereinandergelagert und das Zeichnen des Hintergrunds nur dann ausgelöst, wenn er betroffen war, aber auch dann flackerte es - weil eben der Vordergrund - also das überlagerte Objekt - kurz verschwand. Sind ja nur Millisekunden, aber trotzdem.

Hallo, Hubert.

Mit den Mixmodes habe ich schon ein bisschen herumgespielt, aber das war auch eher ein Schuss in den Ofen. Gradienten und Icons reagieren seltsam (Tendenz: überhaupt nicht) hierauf, und ein aktiver Termin besteht aus insgesamt acht Elementen, wobei für die abgerundete Gradientenfüllung auch noch doppelt geclippt wird, weil es keine abgerundeten Gradienten gibt (es sei denn, man malt linienweise, was ich auch schon ausprobiert habe, aber das generiert auf langsamen Rechnern erschütternde Latenzen). Die maximale Eingrenzung des zu zeichnenden Bereichs habe ich schon vorgenommen, aber nicht (mehr) über die Begrenzung von InvalidateRect(), sondern über GraPathClip() - das ist schneller, hat aber dieselbe Wirkung. Bei so einem kleinen Element wie einer Analoguhr (ich habe ja auch eine gebaut, schon vor Jahren) merkt man's einfach nicht, oder man mixt eben, aber - siehe oben.

Dennoch danke für die Anregungen. Die meisten davon habe ich nur leider schon ausprobiert. :cry:
Herzlich,
Tom
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12909
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 46 Mal

Re: Ownerdrawing - Frage an die GRA-Profis

Beitrag von AUGE_OHR »

Tom hat geschrieben:... wobei für die abgerundete Gradientenfüllung auch noch doppelt geclippt wird, weil es keine abgerundeten Gradienten gibt ...
und damit wären wir wieder bei meinem Vorschlag denn das Problem mit den "runden Ecken" war doch ein Teil des Thema´s.

Code: Alles auswählen

DLLFUNCTION SetWindowRgn(hHwnd,hRgn,bRedraw) USING STDCALL FROM USER32.DLL
   //
   // now construct a Region and call its API function
   //
   hRgn := CreateEllipticRgn(nLeftRect,nTopRect,nRightRect,nBottomRect)
   SetWindowRgn(hHwnd,hRgn,.t.)
da ich noch nicht weiss ob du beim "bewegen" oder beim "drop" das flickern hast gehe ich zunächst mal auf das "bewegen".

Frage : haben alle Child´s den Dialog (drawingArea) als Parent ?

das wäre ja der gewöhnlich Fall in Xbase++ ... und das Problem. man kann zwar Childs "aussparen" (clipsilbings) aber sobald der Dialog die WM_PAINT Message erhält baut er das Bild auf. ich hab zwar in meinem Devcon Demo mit den API Functionen (SendMessageA) gearbeitet aber die Idee geht auch mit Xbase++ "pure" wie ich zeigte.

nimm einen anderen Device Content (hDC) und "male" das ganze in eine eigenes "unsichtbares" ( transparent) Fenster.
wenn ich nun das Fenster bewege sieht man "nur" noch an den "runden Ecken" das "re-paint" des Dialog. erst beim "drop" wird der "Inhalt" des Fensters in den Dialog "übertragen".

die Geschichte mit dem Bitmap war nur eine zusätzliche Spielerei ... hDC -> Bitmap ... kein Problem.
gruss by OHR
Jimmy
Benutzeravatar
azzo
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 483
Registriert: So, 28. Mär 2010 19:21
Danksagung erhalten: 11 Mal

Re: Ownerdrawing - Frage an die GRA-Profis

Beitrag von azzo »

Hallo Tom,

ich zeichne einfach Linien und schreibe direkt mit drawText auf den screen.
Ich glaube, mit echten Controls wird es mit mehreren Terminen zu langsam.
mfg
Otto

Bild
Antworten