I have investigated this problem across some different computers with theming/classic-theme and/or theme support disabled in my app...
Problem when Windows is configured to draw the window while dragged + theme drawing enabled:
My primary app window stutters greatly when dragged around screen. It is even so bad that if I drag the window e.g. 10 inches left and releases mouse button... The Window will then continue to move around the screen for 2-5 seconds more!
Speculation #1
I think the message queue may be flooded with paint-message related stuff meaning the move-messages get delayed? (which then again causes paints) Maybe some postmessage/sendmessage queuing going wrong.
What I have tried
I created some code that went through all controls in my form and disabled all events I could think of + called .Hide on them all -- this has no effect on the problem... However, I then created some code that went through all controls and removed them entirely -- this solves the problem if I remove say 50-80% of the controls.
Speculation #2
Is Windows draw style theming also done on controls not visible? (e.g. if placed on a TTabSheet not currently active?)
Other notes
In all honesty my form is very large (I spit out 7 different tools which all use most of it)
It is possible a TFrame based solution - as long as not loaded into memory - could solve this. But there are many problem in this... For one I have not abstracted reading e.g. options... I.e. I read myCheckbox.Checked to determine if a given option is enabled before passing it on my separated business logic.
But it is possible if I had a layer inbetween I could load TFrames as necessary... But it will be major work to convert to this.
...
Any ideas on how to workaround this? Reducing the problem is enough... I am thinking about:
a) Removing what I can.
b) Replacing what I can with stuff not style theme drawn. (E.g. "debug" controls I use myself to understand what is going on)
c) Maybe loading some stuff in TFrame instead
d) Trying to figure out why invisible controls cause problems for the style theme drawing... Could I have them ignored somehow?
e) Disable themning while drawing?
f) Disable having window drawn while dragged even if Windows is configured to draw Windows while they are being dragged.
g) WM_WINDOWPOSCHANGING / WM_WINDOWPOSCHANGED and disable align + draw while it happens.
Related
We are working with Firemonkey since version 1, and still find difficulties updating components that are currently visible on the screen. There are many 'ways' to request a repaint in Firemonkey, perhaps too many:
Applying a style (ApplyStyle event) - mostly when it becomes visible on screen
Requesting ".repaint" - some components have this
Requesting ".realign" - sometime works, current versions of FMX seem to drop / hide it
Requesting ".invalidate" - some components, mostly forms, have this
Requesting ".invalidateRect" - most components have this
Calling the ApplyStyle event manually - not guaranteed to work and design-wise is incorrect...
Given the lacking documentation for the platform, is there a "well defined" way to change the visual appearance (internal values of a style) when a component is already displayed? I.e. a listboxItem that is already present and visible on screen, a TGrid cell, and so on. Would appreciate your thoughts...
I don't think there's a single unified 'correct way' to refresh the visual of components in Firemonkey.
However, as a recommendation from personal experience, I'd take the .repaint route - this method is at the TControl level, and so it precedes primitives and styled controls (which are generally made up of primitives) and so applies to all visual controls. It also doesn't require parameters, so it's a good all-round solution.
I have noted that Firemonkey has always had an issue correctly repainting controls of it's own accord. Often I'm left with a 'shadow' of the previous visual of a control/primitive, and must call .repaint manually to update it. This got noticeably worse with FM2 and FM3 (presumably due to optimizations made for mobile platforms), and so doing a manual .repaint -- especially where effects such as TGlow and moving or rotating controls/primitives are concerned, has become a standard practice for me.
I am using Delphi XE3.
When I create a new VCL project and drop a TToolbar on it, everything works fine - except when I activate Form1.DoubleBuffered.
From that moment on, drawing of the toolbar is broken - in designtime, it's either black, transparent, or parts of the IDE (statusbar, toolbar, etc.) are copied into it. It changes between these options when I click on it and when I change to source code (F12) and back.
In runtime, it's always black.
With DrawingStyle=dsGradient, everything works as expected. Switching back to dsNormal breaks it again.
Deactivating Form1.DoubleBuffered repairs it.
Any hints how to work around that issue?
In my opinion the solution is to set TForm.DoubleBuffered to False. Using a value of True causes all sorts of other problems. This property worked reasonably well before XP themes, but since their arrival, using TForm.DoubleBuffered has not been viable, in my view.
In addition to the problems you have encountered, I've come across lots of painting flaws when using the Windows Basic theme. I know that's not mainstream, but I happen to see that a lot with remote access. And there's more. When you double buffer a form you stop the theme animation from working. For example, a default button pulses to indicate that it is the default button.
If you get resize flickering without double buffering the form, use the ideas from my answer to another question. From the comments it seems that the flickering you wish to combat is in a paint box. I obviously don't know the details, but my experience and instincts say that you should be able to deal quite easily with that flickering at a local level. There surely should be no need for the global form wide double buffering.
As reported in this article, When not to use DoubleBuffered, some controls like TToolBar and TRichEdit don't work well with the DoubleBuffered property set to true.
The reason be be found in documentation, TWinControl.DoubleBuffered, where some WinControls can't draw themselves on a temporary bitmap (as happens when DoubleBuffered is true).
One workaround can be to put the TToolBar on a TPanel.
I'm working on a Windows Deskband in Delphi XE2 for Windows XP, Vista and 7 (Win32 and Win64)...
I've implemented all the necessary interfaces (ITrayDeskBand, IDeskBandInfo, IDeskBand2, IDeskBand) in my code, and that all works exactly as it should (there are no warnings on Vista/7 complaining about compatibility as others have experienced).
The problem I have is that my Deskband Form appears with a non-transparent band. Also, only certain Controls are displaying (in this case TBitBtn and TImage containing a PNG). I need it to display TEdit and TComboBox objects properly too, but they won't appear at all.
I've tried enabling GlassFrame and SheetOfGlass properties on my Form, but this doesn't help one bit.
Furthermore, the Form itself is exceeding the top boundary of the Taskbar, meaning you cannot (for example) resize the Taskbar if the cursor is in-line with the top of the Taskbar immediately above my Deskband.
I believe there is something Delphi's VCL TForm type is doing behind the scenes which renders the TForm type incompatible as a Deskband container... but this is just a suspicion.
Here's a screenshot illustrating the various problems:
As you can see (above), the Deskband's Form is pale (instead of Transparent), it overlaps the top of the Taskbar (preventing resizing and Autohide triggering when the Taskbar is "hidden")
Any ideas?
UPDATE 1
Okay, I have been playing around and noticed that a totally different behaviour is observed when creating a TToolBar control to be used for the Deskband, rather than a form:
Notice there are three TToolButton controls (with their text virtually invisible due to the Glass theme)? There should also be a TEdit and TComboBox between two separators, but these refuse to display at all.
Also notice the artefacting (the repetition of actual Taskbar Icons)?
I'm not sure if this is a step in the right direction or not, but it might help you (or others) to deduce a solution!
Okay... I've finally figured this out, and it is the most absurd thing I've ever come across.
I'm posting my findings here for the benefit of others (to save you going through the nuisance I've just been through).
To get all of the controls on your Deskband Form to display and function properly, simply set the Visible property of your Form (in the IDE designer) to True.
Ridiculous, I know, but it works and is easily repeatable.
It not just my curiosity, recently I've received a bugreport concerning one of my AS3 applications. This bug can be reproduced only if the quality in flash player is set to LOW (HIGH/MEDIUM - everything is ok). The bug changes the application behaviour, but it's a mystery for me, why it happens only for LOW quality while quality is said to influence rendering and visual appearance, not the code or behaviour.
Briefly, I have a menu panel (MovieClip) with several items (also MovieClips). Very simple, it appears on a screen after a MouseEvent and a user moves a cursor from one element down to another. When the cursor reaches the edge of the second item, the menu suddenly disappears.
In my code panel hiding is set on mouse click or mouse out.
Personally, I think, that the problem is in Tweener, I have to use that old piece of code. The menu panel is shown when mouse is above a user icon, and concurrently with the help of Tweener I produce some simple effects on this icon.
I have explored adobe and firefox (my app is for web browsers and the bug is reported for firefox) bugtrackers, but so far I have found nothing. Maybe misbehaviour of flash player 11 with Arrays, already fixed... I've run out of ideas.
From the docs:
LOW
Specifies low rendering quality: graphics are not anti-aliased, and bitmaps are not smoothed.
If it only happens when rendering it set to low, then it's probably a timing issue - i.e., the bug has always been there, but because you're wrapping up rendering earlier, you can trigger then bug. Is the bug reporter's computer a slow one? Is there a lot happening at once? Is the menu being removed, set to invisible, or repositioned?
Like #jeremynealbrown said, try and separate out your class to a simple project to make sure there's nothing wrong with your logic there.
Another method, override the removeChild() method, and visible and x and y properties to see which one is setting it, then put traces before all calls that call these to see what's triggering it.
If you think the problem is in Tweener, add a MOUSE_OVER listener to the menu panel that calls something like removeAllTweens(), no matter the state of the menu panel. If the bug doesn't happen anymore, this will show you that it's related to the tween engine.
i have a flow panel that i'm adding extra items to it at runtime based on whether they have chosen to show all the items. that's all works fine; the expansion is controlled by a toolbar button.
the trouble is we'd like the user to be able to move his mouse over the "+" sign to expand the section.
initially i looked at TSpeedButton (OnMouseEnter) but even when it's "Flat", the focus rectangle still shows and so the glyph isn't centered. the main problem with this solution is it's appearance.
then i looked at making a descendant of TImage. that's a bit "unconventional" but it'd work. in OnMouseEnter or OnClick, it'd toggle an internal boolean "Expanded" flag and then load the appropriate picture from a resource. i have a dislike for unconventional solutions like that.
i need to add it to a few different screens so it's probably prudent for me to have/build a component for this. i have JVCL but i don't see anything suitable offhand.
thank you for your comments/help!
I always liked the approach used by the ModelMaker Code Explorer.
For example, when you're adding a new method, some rarely-used stuff is displayed collapsed ('Options and Directives' in the image below).
(source: 17slon.com)
When you hover over the text, you notice that it's actually a flat button. (Except that it's not - I believe Gerrit does some custom painting magic here).
(source: 17slon.com)
When you click this button, a panel appears. Button is still there, but with a new image. You can click it to close the panel.
(source: 17slon.com)
The state of this toggle button is preserved between sessions. IOW, even if you restart the Delphi, next tima you invoke 'Add Method', the 'Options and Directives' panel will appear exactly as you left it the last time.
i have a dislike for unconventional solutions like that.
Over the past few years, I have grown a bit suspicious of unconventional UI solutions — which is what you seem to be creating here. Why not just use a button that the user actually has to click? That seems to be much more common in the software I use, be it MS Office or programming utilities. Also, I'd make the button somewhat larger: in the screenshot, it really seems like a tiny little thing you have to target with your mouse cursor. Oh well, and if I'm bugging you with advise you haven't asked for anyway, why not give it ">>" as a caption instead of "+"? And if you'd give it a textual caption with a mnemonic as well, it'd actually be keyboard accessible. All this should make your UI better and more intuitive. I guess.
I do apologize for not answering your question, but I hope you'll spend 2 minutes thinking whether your users would actually prefer this solution :-)
Good luck!
Actually, I think that using a TImage in this situation is pretty conventional. I have seen many people suggest using the TImage, when either the TButton, or any of its associates did not have the right amount of control for whatever the developer was trying to do.
Have you tried a TBitBtn? I think when you get rid of the text it centers whatever image you have associated with it. I just checked in Delphi 6, all I have installed on this machine, and it had the MouseMove event.