 |
|
 |
Hello,
I have used your method in owner drawn listboxes, and facing a little problem. I have used the updatewidth function in drawitem. Scrollbars are coming and its scrolling, but since its owner drawn, when i scroll back the text is jumbled up. I am not much experienced in owner drawn controls. Could you give me a few pointers as to what can be done?
Thanks.
"Some guys hack just to get themselves a girlfriend.What a pathetic reason huh ?"
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
 |
Hi,
I'm facing the exact same problem right now, so if you or anyone finally found the fix for this, I'm interested 
Thx
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
hmm..I remmember fixing the problem..I forgot what I did. I will have a look at the code tomorrow and let you know.
Cheers!
"Some guys hack just to get themselves a girlfriend.What a pathetic reason huh ?"
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Great ! I'm looking forward to understanding the root cause of this bug which has been...bugging me for a while
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
 |
|
 |
Hello,
we need this function in a non-MFC program. Maybe someone else need it:
int g_iStoredWidth = 0; void CHListBox::updateWidthAPIFunctions(LPCTSTR s) { HDC pHDC = ::GetDC(m_hWnd); SIZE neededSize; ::GetTextExtentPoint32(pHDC, s, strlen(s), &neededSize); ::ReleaseDC(m_hWnd, pHDC);
if (neededSize.cx > g_iStoredWidth) { g_iStoredWidth = neededSize.cx; LRESULT x = ::SendMessage(m_hWnd, LB_SETHORIZONTALEXTENT, neededSize.cx, 0); } }
Peter
-- modified at 8:27 Wednesday 26th July, 2006
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
An interesting class, which does what it intends too. A few comments:
The use of a non standard naming convention (ie not the hungarian notation[^]) doesn't ease the read of the code. When you select a GDI object in a device context, always re-selected the previously selected object before the destruction of the DC, or you can get GDI leaks. For instance:
{ CClientDC dc(this); CFont *pMyFont = ::GetStockObject(SYSTEM_FONT); CFont *pOldFont = dc.SelectObject(pMyFont); [...] dc.SelectedObject(pOldFont); }
In a 'for' statement, it may not be a good idea to use a method in the 'stop condition', because this method is called for each step. Because the item count doesn't change, it would be better to store it in a variable then use this variable in the condition.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hungarian Notation is a fundamentally Bad Idea because it leads to erroneous and misleading code. Better to not use it than to use it incorrectly.
Stock objects cannot cause resource leaks. So this is not a concern. If I wanted to reset the state, I would not have used SelectObject to restore it, but used SaveDC/RestoreDC
While it is true that the method requires re-evaluation, introducing a temporary variable serves no useful purpose in this case because the overhead is unnoticeable. Therefore, there is no reason to "optimize" something that is several orders of magnitude smaller than the rest of the overhead involved in the computation
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Joseph M. Newcomer wrote: Hungarian Notation is a fundamentally Bad Idea because it leads to erroneous and misleading code. Better to not use it than to use it incorrectly. It is a matter of taste then. Anyway, Hungarian notation or not, simple standard MFC conventions as prefixing member attributes with "m_" simplifies the understanding of the code IMHO.
Joseph M. Newcomer wrote: Stock objects cannot cause resource leaks In that case you are right. Moreover, my code was false. Getting a stock font would be
CFont *pFont = CFont::FromHandle((HFONT)::GetStockObject(SYSTEM_FONT)); I still believe it is more efficient to re-select the previously selected object rather than using SaveDC/RestoreDC which uses the stack, a limited resource I prefer to manage it closely.
Joseph M. Newcomer wrote: there is no reason to "optimize" something that is several orders of magnitude smaller than the rest of the overhead involved in the computation You sound like a VB coder - Nah, just kidding 
What I fear is that most people will use the "method in test" by convenience, without thinking about the consequences. Something done by the people who wrote the code I'm working on, people who didn't realize that when it involves thousands of elements in imbricated loops, it may have a deep impact on performances.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I find the m_ notation to be about as silly. You're right, it is a matter of taste. If you can't see the local variables nearby, the function is probably too long anyway. The use of m_ leads to even sillier conventions like insisting that global variables be notated as g_ and local variables as l_. You would probably not believe the number of times I see people writing
void SomeFunction(int m_thing, LPCTSTR g_other)
and the excuse they give is that "Well, I had written the code to use m_thing and g_other, and then I decided to just pass them as parameters". At least by avoiding the conventions entirely, I force the programmer to ***actually look at the code*** instead of making possibly invalid assumptions.
Efficiency is hardly an issue for SaveDC/RestoreDC. You are about to execute a couple hundred thousand instructions, or have just finished, and the cost of SaveDC/RestoreDC is minimal by comparison. Also, for those who try to play the "efficiency" card, remember that the biggest overhead is the kernel call itself; one SaveDC/RestoreDC pair compared with a large number of SelectObject(old_whatever) becomes a debatable point. I get very, very suspicious of people who play the efficiency card at the sacrifice of code clarity (there are over 30 parameters to a DC that must be saved; I've seen even simple graphics code use dozens of variables to hold intermediate state, and the inevitable confusion ensues. So I avoid it all)
I have not hit a limit on the SaveDC/RestoreDC stack size; no stack size limit is documented, and I've been nested fairly deeply. Perhaps I'll write a little test program to see when the DC stack overflows...but unless you have a documented llimit, claiming this is a limited resource is difficult to justify.
When there are thousands of calls in a tight loop, and the call represents a significant cost of the loop, it is worth worrying about. The rest of the time, write simple code. The older I get, the more I appreciate the value of really simple code. Having spent 15 years doing performance analysis (I wrote the performance analysis tool and spent a lot of time with a lot of people trying to optimize their code), I've discovered that program architecture matters, and lines of code rarely matter. In the absence of evidence of performance problems, "optimizing" them away just wastes time and energy. Once you've profiled your program, and know EXACTLY where the time is going, is the time to start worrying about how to make the inner loops faster.
I've seen inner loops that gained four orders of magnitude performance improvement by simply avoiding using the storage allocator, and those which lost six orders of magnitude performance by ignoring page faults as a concept. Both were found by getting actual data. Interestingly enough, in the first case, the programmer was "optimizing" the wrong part of the loop; it was small, tight, unintelligible, and irrelevant. Once the allocator bottleneck was removed, the "optimizations" accounted for only a 10% improvement in the loop, which was an unmeasuable percentage of the program execution. In the second case, the programmer had worked for weeks to get the code as small, fast, and bizarrely convoluted as possible, and then walked over a couple megabytes of data on a 512K machine supporting multiple users. We threw the "optimized" code out, used the "unoptimized" computation but worked on the data a couple pages at a time, and dropped the computation from hours to under a minute. Also, check out my essay "Optimization--your worst enemy". By focusing on lines of code, major architectural issues are often ignored. Only a profiler can tell you the real truth.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Joseph M. Newcomer wrote: void SomeFunction(int m_thing, LPCTSTR g_other) Somebody writing that just proves(s)he didn't understand the concepts of OO languages. It isn't a reason to condemn the standard practices. On the contrary, in that case it helps to show the coder needs complementary explanations.
Joseph M. Newcomer wrote: I force the programmer to ***actually look at the code*** instead of making possibly invalid assumptions. Following this logic, you should call your methods M1 and M2, your variables a, b, c, your parameters p1, p2...
Joseph M. Newcomer wrote: Efficiency is hardly an issue for SaveDC/RestoreDC. You are about to execute a couple hundred thousand instructions, or have just finished, and the cost of SaveDC/RestoreDC is minimal by comparison. The problem is not about performance, it is about the managment of a limited resource. As you says, SaveDC/RestoreDC pushes more than 30 parameters in the stack.
Joseph M. Newcomer wrote: . I get very, very suspicious of people who play the efficiency card at the sacrifice of code clarity You are right, code clarity is something very important. Then the use of standard conventions 
Joseph M. Newcomer wrote: no stack size limit is documented, and I've been nested fairly deeply. True, since the end of 16-bits environment programming, stack size is theorically no more a problem. For a thread the stack size is now 1 MB[^]. Stack overflows are now something rare, unless the coder goes wild. Nonetheless, the stack limited size should be a parameter a coder should be aware of. If he knowingly chooses to extensively use it, there is no problem, as long as he knws what he does (and then we go back on the point we are in fact both enforcing: know what you do, make your choice according to reality).
Joseph M. Newcomer wrote: The older I get, the more I appreciate the value of really simple code Agreed.
Joseph M. Newcomer wrote: Once you've profiled your program, and know EXACTLY where the time is going, is the time to start worrying about how to make the inner loops faster. The efforts are not the same: For instance, I work on a scientific module horribly written. it took me two days to simply modify loops code and gain 20% in performance. By redesigning the architecture I could probably gain much more, but it will take me weeks, perhaps months. In the end I will probably do that if I am allowed too, but the customers can use right now something 20% more efficient. I agree with you to say: "think about your design, it is the most important thing". But I would add: "But don't ruin it by coding it without care".
Joseph M. Newcomer wrote: check out my essay "Optimization--your worst enemy" Any link?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
no stack size limit is documented, and I've been nested fairly deeply.
True, since the end of 16-bits environment programming, stack size is theorically no more a problem. For a thread the stack size is now 1 MB[^]. Stack overflows are now something rare, unless the coder goes wild. Nonetheless, the stack limited size should be a parameter a coder should be aware of ***** I was talking about the SaveDC stack size, not the execution stack size; the two are basically unrelated. And SaveDC space is *not* a "limited resource" that requires "management". My point is that if you talk about "efficiency", then you have to weigh the cost of making a copy of 30 parameters inside the kernel with a single call against the cost of all the kernel calls to restore them one at a time. Using SaveDC results in conceptual simplicity, but the price you pay is that it runs faster. ***** It is also true that you can squeeze 20% out of anything, but all my years of performance analysis demonstrated to me that you can get an order of magnitude gain or loss in the architecture phase.
OTOH, I needed to do an FFT on some data. I allocated an array of doubles, copied the 16-bit integers into it one at a time, applied the FFT, scanned it for min/max values, rescaled the data back to 16-bit integers, and displayed a graph. I did it in the slow, stupid way as proof-of-concept, but it worked so fast that we never rewrote it. It appears to be instantaneous as far as the user is concerned; as the user moves a "segment selector" along the audio sample with the arrow keys the waveform seamlessly redraws. But where we spent effort was in the I/O buffering, to avoid sound glitches.
Peformance never matters until it matters, then it matters a lot. That's why profiling is so important when performance becomes an issue; it says where to focus your efforts. I know a lot of really sophisticated hacks to improve performance, but I like to put the effort where it matters, and I've found the architecture level is where the big factors are. 2X is common, 5X is not bad, and 10X is possible in some cases. But, as you say, it is often harder to do.
It's here on CodeProject, or you can look on my mvp tips site, www.flounder.com/mvp_tips.htm
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Joseph M. Newcomer wrote: I was talking about the SaveDC stack size, You're right, I read the documentation too fast: SaveDC stores data in a context stack, not in the execution stack as I thought at first. My fault.
Joseph M. Newcomer wrote: www.flounder.com/mvp_tips.htm[^] Thanks, I'll have a look at it.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
 |
Here is a link to an MSDN article on this subject :
http://support.microsoft.com/support/kb/articles/Q66/3/70.asp
It has a bit more background information.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
This is just what I need! Now if I can just get it working...
I'm running VC++6.0. I followed your instructions to delete my .clw file, then reinitialized the Class Wizard. The HListBox files are properly included, and I am fairly certain that the object exists. But when I try to link everything together, I get a bunch of linker errors:
--------------------Configuration: proj - Win32 Debug-------------------- Linking... proj.obj : error LNK2001: unresolved external symbol "public: virtual __thiscall CHListBox::~CHListBox(void)" (??1CHListBox@@UAE@XZ) projDlg.obj : error LNK2001: unresolved external symbol "public: virtual __thiscall CHListBox::~CHListBox(void)" (??1CHListBox@@UAE@XZ) projDlg.obj : error LNK2001: unresolved external symbol "public: __thiscall CHListBox::CHListBox(void)" (??0CHListBox@@QAE@XZ) Debug/proj.exe : fatal error LNK1120: 2 unresolved externals Error executing link.exe.
fc.exe - 4 error(s), 0 warning(s)
Any suggestions?
P.S. Your .ico file is missing from your zip file 
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
Since the AddString and DeleteString and such are not virtual it won't work with pointers to CListBox. You will be better off by intercepting LB_* messagges in WindowProc and calculating there...
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Agree entirely, it works just fine like this. Nor do you need to cache the width value - GetHorizontalExtent() will do this for you.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|