Tuesday, April 15, 2008
Programming Pointers
Of interest to me were the following:
Linkage in C and C++
Storage class specifiers and storage duration
Thursday, March 06, 2008
Create A Library For Someone Else
Everyone should write code for some one else. The back and forth of hammering out interfaces is just a part of it. The real learning comes from the other person doing things you never thought they would. When the complaints and bugs come back you get the chance to figure out where you went wrong.
Here are my favorites from C++ Win32 programming:
- Misusing or not using an interface because they "didn't understand it"? "Then why didn't you ask", you mutter.
- Passing the wrong parameters, but somehow it "just works but I don't know how", they quip.
- Threading/Concurrency. This is the biggy. You probably never expected that object to be used on a different thread did you? Whose job was it to make this object safe, yours or mine?
- Blocking, a corollary to the above. Your method call blocks, but the caller doesn't want it to. They almost never do.
Your code becomes more useful because it is easier to use. It solves more people’s problems and they look forward to using it.
In the end you become a better programmer. You find even the interface that you create just for you are more useful. "Cool, I can use that same widget X in program Y without any changes." That is when you know you have got it right.
So, all I am asking is spend 5 minutes during the design and think, "How could someone else abuse this?" It will make for a better design. Besides, who knows, you might be the one that wants to "abuse" the interface later on. Let's make sure you don't have to.
Wednesday, March 05, 2008
Scrolling Windows
At GIPS, we have our own CWnd derived scroll bar. It is just a "regular old" window with the customary parts of a scroll bar. Up, Down buttons, track and thumb. You attach a window to a scroll bar (not vice versa as you would expect) and it forwards scrolling events to the attached window.
The problem is that scrolling performance is terrible when dragging the thumb
quickly. When you do so each WM_MOUSEMOVE message might span many (10's) pixels
equating to several (2 or more) scroll bar position changes. Root cause of poor
scrolling performance is we process each position change individually. For example if scrolling up we do the following.
for ( UINT i = lastScrollPos; i > newPosition; i-- )
{
attachedWindow->SendMessage(
message,
MAKEWPARAM(SB_LINEUP,0),
NULL );
}
In my case the loop above was running 2-14 times. The solution was to change SB_LINEDOWN to SB_THUMBTRACK and remove the loop.
m_slaveWindow->SendMessage(
message,
MAKEWPARAM( SB_THUMBTRACK, newPosition ),
NULL );
I was still left with an additional problem. List-View doesn't seem to like to get SB_THUMBTRACK directly as noted on CodeGuru:
List control will call GetScrolInfo function to get the current scroll box tracking position, so it is necessary to set the tracking position before sending WM_HSCROLL/WM_VSCROLL(TH_THUMBTRACK) message to it.
Unfortunately, SetScrollInfo function does not work when using
Note that ListCtrl really likes to get scroll notification via LVM_SCROLL. However, the general purpose scroll bar doesn't want to track that level of details. SPY++ revealed that List-View sends a WM_SYSCOMMAND / SC_VSCROLL followed by WM_VSCROLL / TH_THUMBTACK. I tried to send WM_SYSCOMMAND / SC_VSCROLL to no avail.
To resolve the List-View issue I changed the scroll bar to take a boolean indicating if we should use line by line scrolling. So windows, that require line by line scrolling can get the original unoptimized version. By default others get the optimized version.
Related Links:
CListCtrl Scroll Messages
How to skin CListCtrl incuding scrollbars and column headers
