When I try to set the width of a multiline EditBox widget, it flickers for a moment, then gets set.
Is there a way to get rid of the flickering? Or, alternatively, is there a workaround?
It might be a problem with the way the UI rendering is optimized. Try changing your UIFaster setting as described here: http://www.wowwiki.com/CVar_UIFaster
I've usually seen this as a result of multiple calls to :SetWidth() occurring in quick succession. There are two ways this can happen — (a) it's genuinely getting called multiple times, or (b) it's been hooked/replaced with another function which is internally causing multiple calls. As a quick test, try running the following command (or equivalent) via the WoW chat window while your edit box is visible:
/script MyEditBox:SetWidth(100)
If the size changes without flicker, you've got scenario A — go over your addon's logic paths and make sure :SetWidth() is only being called when appropriate (and only once). If it does flicker, you're probably looking at screnario B (or, of course, the UI issue Cogwheel mentions). This may be harder to debug, unless you're hooking/replacing SetWidth yourself, but a good first step would be to disable all other addons and see if the problem resolves itself. If not, my first guess would be a library issue (assuming you're using any).
Related
When pressing the F1 key, the win32 API first sends the appropriate key message then sends a WM_HELPmessage to the control that has the focus.
As it does not process it, it gets sent up the parenting chain all the way to the form which reacts to the message.
In Delphi (XE7) this happens because of calls to CallWindowProc inside Vcl.Controls.TWinControl.DefaultHandler
While this works fine in pretty much all locations inside my applications, there is one place where WM_HELP never reaches the top form.
Trying to reproduce it, I came up with a test application that you may find here:
http://obones.free.fr/wm_help.zip
After having built the application and started it, place the focus inside the In SubLevel or Level 1 edits and press F1.
You will see that WM_HELP is caught by the form.
Now, if you do the same inside In SubLevel2 or Level 15 edits you will see that nothing is logged, the form never sees WM_HELP
Tracing in the VCL I found out that for those deep levels, the calls to CallWindowProc inside Vcl.Controls.TWinControl.DefaultHandler immediately returns on one of the controls in the hierarchy, thus preventing the form from ever receiving the message.
However, I couldn't figure out why the Win32 API code thinks it should not propagate the message anymore, except for one thing: If I remove the WH_CALLWNDPROC hook, then everything is back to normal.
You can see the effect of disabling it if you uncheck the Use hook checkbox.
Now, one will argue that I shouldn't have such deep hierarchies of components, and I agree. However, the structure in the center with two frames inside one another is directly inspired by what's in the application where I noticed the issue.
This means that it can be quite easy to trigger the problem without actually noticing it. Hopefully, in my case, I can remove a few panels and go back below the limit.
But did anyone encounter the situation before? If yes, were you able to solve it? Or is this a known behavior of the Win32 API?
This is caused by a "Windows kernel stack overflow" that happens if you send window messages recursively. On a 64 bit Windows the kernel stack overflow happens much faster than on a 32 bit Windows.
This bug also caused the VCL to not resize deeply nested controls correctly before it got fixed by changing the recursive AlignControls code to (my) iterative version (more about the stack overflow: http://news.jrsoftware.org/news/toolbar2000/msg07779.html)
In our software we have issues with asynchronous execution of events. Sometimes one function will "break into" another one with all kinds of weird results.
I'm dealing here with user-input and timers that fire events.
The issue is that rather then executing the code tied to the events one by one, it's done at the first possible moment that Delphi gives a window for it: application.processmessages. This gives problems in that sometimes half of function A gets done, then function B "breaks in", gets done and after that , the last half of function A gets done. This can give "surprising" results.
Are there good ways to deal with this?
Things I tried:
--
Using a "busy-flag", this has some ups and downs, mostly that everything you do has to know of it.
Removing all application.processmessages where I can. This has pretty good results. But we're relying on some 3rd party components which I found out also fire application.processmessages.
Next I was thinking of trying building some kind of "command-queue" where I can receive my events and fire them in a fifo way.
Apart from rebuilding everything we have from the ground up, are there other/better ways to tackle these issues?
The best way is to eliminate the call to Application.ProcessMessages. Most of the time there is other ways to do what Application.ProcessMessages is supposed to do. You'll need to take a closer look why you need that call, and then find a better solution. For example, you don't need Application.ProcessMessages to update the UI. There is other ways to do that.
If a 3rd party component is calling Application.ProcessMessages then contact that vendor that they should replace this call with a better suited function. If this is not an option, you can try using workarounds like using that component in a thread (if possible). Or create an invisible modal window and execute the methods of the component inside the ShowModal function. That will at least avoid user input messages. (The "invisible modal window" is a Form with BorderStyle=bsNone, size=1×1 and 100% transparency).
Are there good ways to deal with this?
First eliminate all your use of ProcessMessages. As you discovered, it screws up timer event handlers when called from there. Used in other places, it is often subject to race conditions and may hide the real problem. Find out what that problem is and solve it.
But we're relying on some 3rd party components which I found out also fire application.processmessages.
Timer Event handlers are supposed to do only short time work. If you are calling ProcessMessages via a call to a 3rd party library inside a timer event handler, eliminate that call. There is no other cure, except rewriting the library or calling it in another way.
Apart from rebuilding everything we have from the ground up, are there other/better ways to tackle these issues?
Normally you can do background work in threads as well, providing the rules of not calling any VCL RTL methods directly are followed. Here it is not possible if the 3rd party component is calling ProcessMessages.
If you can't alter the 3rd party component, there is possibility to post a message to your form, and put the call in the method that handles this message. With a modern Delphi you could use DelayedAction by #MasonWheeler. But I really recommend you to take the "hard" way and fix the 3rd party lib instead.
I have a problem I cannot solve. Of course here I just expect to have a suggestion that can help me to find a solution.
Basically my application is full of runtime generated TPopupMenuItems (while all the TPopupMenus are hardcoded). In some cases what I do is simply hide/show or enable/disable items, in other cases I create items at runtime.
In some machines only, after leaving the application running for days (2 or more) the popupmenus don't work anymore correctly.
The behaviour is:
all the TPopupmenu items look are the same, and execute the same action.
The action is the one performed by the first TPopupMenuItem of the application (the first generated at runtime when the application starts, this is the only hint I have).
Imagine in correct scenario I have (in a 3-items-TPopupMenu):
Item23
Item24
Item25
after the problem I see:
Item1
Item1
Item1
(where Item1 is the TPopupMenuItem belonging to another TPopupMenu).
Does this tell you something?
Thanks.
Update:
I tried to look at the code of my popupmenus and I found what could be a common cause, and this explains also why FastMM4 didn't find this:
while mnuItem.Count > 0 do
mnuItem.Delete(0);
Delete (I just read in the documentation) doesn't free the item, I should call free instead. Anyway when closing the application the main popupmenus are freed correctly, and FastMM4 doesn't complain. So this is probably the solution, now I don't know why Delete was used, I didn't write that code.
Further update:
I tried to make a sample application, I couldn't reproduce the problem, but for sure I noticed that using this is much more performant (I tried a loop with 10000 recursions):
while mnuItem.Count > 0 do
mnuItem.Items[0].Free;
I will try for this in my app (but I need to let some days pass to really know if I got the problem, ayway for sure this is a major improvement anyway).
I confirm that the problem was linked to Delete instead of Free. Popupmenu wsa refreshed every minute on the machines that had the problem (so it was not OS or HW specific, just config specific). Then according to user settings the menu could have 10 to 100 items, so leaving it idle for days made it possible to hit the handle limit.
By the way it also makes no sense to refresh the popupmenu in that way, so I found also an optimizaion removed a bug.
Did you check for memory leakage and handles that aren't freed?
I have a D2006 app that contains a page control and various grids, etc on the tabs. When I resize the main form (which ripples through and resizes just about everything on the form that is aligned to something), I experience long delays, like several seconds. The app freezes, the idle handler is not called and running threads appear to suspend also.
I have tries pausing execution in the IDE while this is happening in an attempt to break execution while it is in the troublesome code, but the IDE is not taking messages.
Obviously I'm not expecting anyone to point me at some errant piece of code, but I'm after debugging approaches that might help me. I have extensive execution timing code throughout the app, and the long delays don't show up in any of the data. For example, the execution time of the main form OnResize handler is minimal.
If you want to find out what's actually taking up your time, try a profiler. Sampling Profiler could answer your question pretty easily, especially if you're able to find the beginning and the end of the section of code that's causing trouble and insert OutputDebugString statements around it to narrow down the profiling.
OK. Problem solved. I noticed that the problem only occurred when I had command-line switches enabled to log some debug info. The debug info included some HTTP responses that were written to a debug log (a TMemo) on one of the tabs. When the HTTP response included a large block with no CR/LFs the TMemo wrapped it. Whenever I resized the main form, the TMemo resized and the control had to render the text again with the new word wrapping.
To demonstrate:
start a new Delphi project
drop a TMemo onto the form
align it to Client
compile and run
paste a large amount of text into the TMemo
resize the main form
I won't award myself the answer, as I hadn't really provided enough info for anybody else to solve it.
BTW #Mason - would SamplingProfiler have picked this one up - given that the execution is inside the VCL, and not in my code?
A brute-force approach that may give results.... Put a debug message to OutputDebugString() from every re-size event, sending the name of the control as the string to be displayed. This may show you which ones are being called "a lot".
You may have a situation where controls are bumping each other, setting off cascading re-size events. Like 3 siblings in the back seat of a compact car, once they start jostling for position, it can take a while for them to "settle down".
Don't make me turn this car arround....
The debug log (viewable in the IDE, or with an external ODS viewer), may show you which ones are causing the most trouble, if they appear multiple times for one "user-initiated re-size event".
Run your application in AQTime's performance profiler (included with XE, but you can get a time-limited version from their website).
Do some fanatic resizing for a while, and then stop the application.
After that, you'll see exactly which function was called many times, and where most time was spent.
Experiencing jquery in rails through .js.erb templates; but completely puzzled by a simple problem : for some reason, when a certain controller's action is called, it is recalled like two or three times. and on top of that, the number of recalls to the same action increase as the page is used. so i quickly end up with long loops over the same action...
there's a real logic in this bug, but still, can get hat it is and how to solve it.
ay experiences with tose kind of problems ?
Try unbind(ing) the event before attaching it. that helps with my stuff from time to time.
If you are using the live keyword then stop using it. if you are not, then try using it. i know that sounds like rubbish advice but i have done these steps in the past to fix issues exactly like you describe.
also, if on your success of the jquery call, ensure you are not rebinding events on a set of objects defined by a class. that will also add events to controls.