Tag Archives: Code

Serial Port Code Library

Need to interact with some hardware via serial port? I’m having to do some serial port communications in a project at work, and it is officially Not Fun. There was some original code that was doing only reads from the port, and I needed to some significant functionality that would not be possible with the existing code. So rather than writing a ton of code from scratch (well, other than what I will have to do anyway), I tried to find some open-source, commercial-friendly serial port libraries on the Internet.

The only one I could find that seemed to be perfectly suited to the task at hand was Serial Library for C++ by Ramon de Klein. It has a number of classes for various ways of accessing the serial port and handling events, interacting with Windows. It also supports MFC.

The license is LGPL, which makes it’s ok for me to use in the project. As Ramon’s article notes, doing serial port communications from scratch is hard. So reuse what is out there.

If you’re in .Net, you already have some nice classes in the form of System.IO.Ports.SerialPort, which was added in 2.0.

Technorati Tags: , , ,

What’s Wrong with this Code 2 (Answer)

In my previous post, I showed some code that we “fixed” and it caused problems–it actually broke the algorithm.

The bug was in relying on some compiler behavior and the usage of the stack.

Here’s the original (pre-“fix”) code again for reference:

                 for(i = 0; i < overlaySize.cx; i++) {
                    long i1 = (long)((double)i / numXTimes);
                    double xPercent = (double)i / numXTimes - i1;

                    // get the indeces into the data array
                    long lIndex1 = i1 + (j1 * m_DataSize.cx);
                    long lIndex2 = lIndex1 + m_DataSize.cx;

                    double yVal1, yVal2;
                    if(i1 != oldi1) {
                        yVal1 = m_DataArray[lIndex1] + //etc...
                        yVal2 = m_DataArray[lIndex1 + 1] + //etc...

oldi1 = i1; } // figure out the value double theVal = yVal1 + (yVal2 - yVal1) * xPercent;
                }

The answer lies in the realization that yVal1 and yVal2 need to retain their values through each iteration of the loop. It always worked before because the compiler ensured that each time those variables are used, even if they’re not initialized after declaration, they reference the same place in the stack on each loop iteration. By setting them to 0.0 each time, we’re breaking the reuse functionality. Finding this, we realized that is horrible! At the very least, it’s brittle, prone to break if anything went into the loop which altered the stack differently on different iterations.

Thankfully, it was easy to fix. Just move the declarations and initialize them outside the loop.

                double yVal1 = 0.0, yVal2 = 0.0;
                for(i = 0; i < overlaySize.cx; i++) {
                    long i1 = (long)((double)i / numXTimes);
                    double xPercent = (double)i / numXTimes - i1;

                    // get the indeces into the data array
                    long lIndex1 = i1 + (j1 * m_DataSize.cx);
                    long lIndex2 = lIndex1 + m_DataSize.cx;


                    if(i1 != oldi1) {
                        yVal1 = m_DataArray[lIndex1] + //etc...

yVal2 = m_DataArray[lIndex1 + 1] + //etc...
                        oldi1 = i1;
                    }

                    // figure out the value
                    double theVal = yVal1 + (yVal2 - yVal1) * xPercent;
                                
                  }

I don’t know who wrote the brain-dead code in the first place, but…wow.

Anyway, lessons learned?

  1. Test a change like this–I had put some asserts there because I didn’t fully understand what was going on, but it was so long until I ran the code after making the change that I had mostly forgotten about the change.
  2. Turn on strict compiler settings from the get-go. Make it force you to be ultra-precise. It can be VERY painful changing 120,000 lines of C++ code to be warning-free at L4. (But we did it!)
  3. Implement and change separate things separately. While removing compiler warnings, we also converted the codebase to Unicode–most places were using _T(“”), but a few places such as file handling needed special attention. That distracted from finding this problem sooner (“Could it be a file reading problem?”)

What’s Wrong with this Code 2

We’ve been working on our next version of our flagship product at work and, as part of that, we upgraded to Visual C++ 8 (2005) and turned on the most strict compiler settings, warning level 4, more debug runtime checks–basically trying to make everything very strict.

As part of that process, we had to go through the code and fix hundreds (thousands?) of warnings that just became errors.

One area was the following:

                 for(i = 0; i < overlaySize.cx; i++) {
                    long i1 = (long)((double)i / numXTimes);
                    double xPercent = (double)i / numXTimes - i1;

                    // get the indeces into the data array
                    long lIndex1 = i1 + (j1 * m_DataSize.cx);
                    long lIndex2 = lIndex1 + m_DataSize.cx;

                    double yVal1, yVal2;
                    if(i1 != oldi1) {
                        yVal1 = m_DataArray[lIndex1] + //etc...

yVal2 = m_DataArray[lIndex1 + 1] + //etc...
                        oldi1 = i1;
                    }

                    // figure out the value
                    double theVal = yVal1 + (yVal2 - yVal1) * xPercent;
                }

I’ve of course cut out a number of lines from this loop that weren’t relevant to the point.

The compiler flagged yVal1 and yVal2 as being potentially unitialized before they were used. It’s because they’re initialized inside an if statement.

So to remedy this, I initialized them to 0.0:

double yVal1=0.0, yVal2=0.0;
if(i1 != oldi1) {

//etc.

I go on to fix other warnings-become-errors, and we finally create our first build with VC8 a week or two later. Then, we start having problems in one area of the program. A data file is working on looks horrible, and it’s taking 45 minutes to do the calculations instead of 2-3 seconds. What’s going on? It took a while to find it, but find it I did…

There is a serious bug in the code above, which my initializing the variables hid. The answer next time!

A Visual Studio that’s easier on the eyes

After you’ve looked at Visual Studio all day for a few days in a row, the brightness of the white background can really start to bother you, especially as LCD monitors get brighter and brighter. That’s why I’ve become a big fan of Dave Reed’s Dark Side theme for Visual Studio 2005. It took me a few hours to get used to it, but now I’m hooked.

The only thing I changed was the font. I really like Consolas, size 13. Courier New is Courier-Old-and-No-Longer-Used.

At work, I still have to use VS2003 for a project, and keeping it in the older, white background really helps me distinguish which environment I’m in.

How to measure memory use in .Net programs

In developing an important component (which I will discuss soon) for my current personal project, there were a number of different algorithms which I could use to attack the problem. I wasn’t sure which one would be better so I decided to implement each of them and measure their time/memory usage. I have a series of articles planned on those, but first I need to mention how I did the measurement.

 

For the timing, I simply wrapped the API functions for QueryPerformanceCounter and QueryPerformanceFrequency into a C# class. There are plenty of examples out there on the net to do this.

The memory usage is even simpler. The function you need is GC.GetTotalMemory(bool forceFullCollection). This function returns the amount of memory allocated. The little program below demonstrates how to use it.

using System;

namespace MemUsageTest
{
    class Program
    {
        static void Main(string[] args)
        {
            long memStart = GC.GetTotalMemory(true);
            Int32[] myInt = new Int32[4];
            long memEnd = GC.GetTotalMemory(true);

            long diff = memEnd - memStart;

            Console.WriteLine("{0:N0} bytes used", diff);
        }
    }
}

The output on my 32-bit system is “40 bytes used”–16 bytes for integers and 24 bytes of array overhead.

Passing true to GetTotalMemory is important–it gives the garbage collector an opportunity to reclaim all unused memory. There is a caveat, though. If you read the documentation, you’ll notice it says it attempts to discover the amount of bytes in use, and that setting forceFullCollection only gives it an opportunity and waiting a bit before returning. It does NOT guarantee that all unused memory is reclaimed.

As far as my work goes, I’ve noticed that it does a pretty reliable and consistent job.

Technorati Tags: , ,

More on Google interview

This a follow-up to my previous post about my interview process with Google. Once a post gets as long as that one did, I’m sure to forget to say some things. Rather than updating that post, I thought I had enough new to say to warrant a new post.

First is the picture I got of their development process. There are plenty of other places on the Internet about their development process, so I won’t go into detail about what they told me–it pretty much matches up with the available information. It really sounds like they try to match the amount of process required to the specific project at hand. Projects with a huge public impact have lots of process (Google’s front page, indexing, etc.), while those that are newer and much lower impact (stuff in the Labs section, and even graduates of the Labs) have a much more flexible, agile process, designed to get improvements out the door very quickly. I like that–no mandatory bureaucracy where it doesn’t make sense.

Aside from process, however, it seems that they are very intent on giving developers an environment designed to help them succeed. From what I understood, the company actively tries to remove stupid barriers to productivity (needless paperwork, poor IT, bad workstations) and give you whatever you need to do your job how you think best. Obviously, there are rules and standards, but it just sounded more flexible. It really sounded like an ideal development environment: Obstacles removed, needs granted. Now, how much of that is the official “show” they put on for all interviews, who knows, but Google is obviously doing something right.

Bottom-line is that Google is a company of engineers for engineers. They’re the ones in charge of what the company does. That is a very nice place to be if you love coding.

Also, I should mention that the Google Boston office is MUCH smaller than their Mountain View headquarters. The way things are done, while it will still be “Googly”, will most likely have a different feel and pace than at headquarters. I had read many reports on the web about how people worked late hours, on weekends, and basically sacrificed their lives for the company. I did NOT get that impression in Boston. They were definitely smart and very hard working, but it sounded more like the company was flexible and if you got your work done, who cares? (That’s the way things ought to be done for sufficiently self-motivated employees). I did ask about inordinate over-time (mistake on my part?) and work-life balance and I came away with a satisfactory impression. Whether this means Boston is special, or the accounts I read on the Internet were not representative, I don’t know. Probably a lot of the latter, for sure.

I also wanted to address my final link in my last post. I know it can be a little disappointing to read that kind of post and realize it’s not talking about you, because you’re interviewing for jobs. I wouldn’t take it too literally. Maybe my link text is a little black and white. I think the principle is definitely valid, though. The better you are, the more freedom you have to choose where you work and what you work on and the less chance your going to fall into a company’s hiring process. It’s really more about statistics from a company’s point of view of finding the best, not necessarily for individuals.

Hopefully, that’s all I have to say on the subject, but if you have questions, just leave them in the comments and I’ll try to answer them!

My interview experience with Google

(See also part 2 of this article).

A few months ago I received an e-mail from a recruiter at Google asking for an opportunity to talk to me about available development positions. Needless to say, I was pretty excited. I’m fairly happy in my current job, but–it’s GOOGLE. You don’t say no to an interview opportunity at Google.

Like this article? Check out my latest book, Writing High-Performance .NET Code.

I’m writing this account in order to contribute to the meager resources available on the Internet about the Google interview experience. I signed an NDA, so I’m not going to say what the specific questions were, but I think I can give a pretty good idea of my experience. I apologize right now for the length.

I traded a few e-mails with a recruiter in Mountain View. I had a phone conversation with him, wherein he asked me general questions about my skills, desired work locations (giving me a choice of Santa Monica, Mountain View, and Boston). I have no desire to live in California, so I chose Boston. I was then passed to another recruiter, who setup a phone interview with an engineer in Mountain View. There was a false start, when they couldn’t do the interview at the original time, so we postponed.

The phone interview went very quickly. He was very nice and asked about my specific talents, things I enjoy doing, and projects I’d worked on–especially those I listed on my resume. He asked about the ray tracer I wrote in college, since he had an interest in that. He also asked some general questions about the stuff I do for work. Then he got into the technical question. It was an interesting problem, and I asked follow-up questions, talked out loud, wrote things down in front of me (and told him what I was writing and why). I immediately thought of the naive solution–always a good place to start. He was interested in the asymptotic complexity. I knew there were better ways of doing it, so I started thinking of optimizations to the algorithm, trying to come up with ways of caching information, reusing previously-computed values, etc. He gave me some gentle prodding, and I think I understood immediately where he was going. I answered the question fairly well, I though.

And that was it–just a single question. I was surprised. The entire thing lasted less than 30 minutes. I was almost disappointed, and thought–“well, that’s that–I won’t hear back.” I really wasn’t expecting any follow-up.

The next week, I got an e-mail from my recruiter who said I had impressed and was going to get the opportunity for an in-person interview in Boston! They hooked me up to a travel coordinator, as well as the recruiter in Boston.

Very exciting. I had a convenient time to go, so I set that up, took time off from work and went up to Boston, staying in the Cambridge Marriott. Very nice hotel. 40″ flat screen TV in the room ( which I never turned on). All expenses paid for, of course. 🙂 I did have to pay for hotel and food up front, and save the receipts. (And yes, I promptly received a reimbursement check from them a few weeks after I sent them in.)

I arrived on Monday afternoon, figured out Logan International (a very confusing airport, I thought), and got myself to Cambridge, in the heart of MIT, an hour or so later. I checked in, then went walking. I found the building Google is in on the very next block from the hotel. They have a floor in a building that MIT leases to startups, tech incubators, and the like. There are plenty of news articles about the Google Boston office–just…you know, Google for them.

I walked past the ultimate geek bookstore–

Quantum Books. Discount tech books. COOL. I would definitely have to stop there later. Then I got some cheap, awful Chinese food at the food court

right under the hotel. Why? When I could go out on Google’s dime? I think I was just tired and wanted to get back to the hotel soon and start studying.

I ate dinner in the room, took pictures of the wonderful view of the Boston skyline.

Boston Skyline (Day)

Boston Skyline (night)

Studying

What did I study? I brought two books with me: Robert Sedgewick’s Algorithms in C++, and a C++ reference manual. I went over advanced C++ topics, STL, simple sorting and searching algorithms, properties of graphs, big-O, and anything else that popped into my head.

By far the most valuable thing I did was write out algorithms before-hand. I picked something and wrote it out by hand in a notebook. It was hard going at first, but I knew it was the best thing I could do to prepare. I did selection and insertion sort in both array and list form. I did string reversal, bit reversal, bit counting, and binary search. All by hand, without looking in a book at all. As well you might know those simple algorithms, it’s harder than it sounds.

I went to bed relatively early–9:30, and woke up the next morning at about 6. I went to breakfast in the hotel restaurant, got a rather large meal, and then headed to my room to study more. I wrote more algorithms and redid some I had done the previous night.

Oh, I also wrote down in my notebook (beginning on the plane ride up) questions for Google, as well as answers to questions they could ask me (standard interview fare–projects, favorite project, languages, strengths, passions, getting along with people).

My interview was scheduled for 10 am–I checked out at 9:30 and left with my bag (I had everything in a single bag I could carry–it was very heavy) and sat in a little square for a few minutes. At about 9:50, I went in, took the elevator, and was greeted with:

.

. (ready for it?)

.

The Google

Dr. Seuss land! Yes, that was my first thought. I think the door was green, the reception area was very colorful. The receptionist was very nice and asked me to sign in on a computer, which printed a name badge for me. They had some research papers by Google employees on a wall, so I grabbed a couple (their hard drive failure study, and map/reduce). After a few minutes, my Boston recruiter came out and greeted me, offered me a drink from their free fridge, and took me to a small conference room, furnished, it appears, from Ikea. It was simple, clean, and very nice. There was a white board. I would get to know that whiteboard very well.

My first interviewer came in and we got started. I talked about my projects for a bit, they answered my questions, and then we got to the problem. Each interviewer asked me to solve a single problem (could be some sub-problems involved), and I had to do it on paper or on the board. I wrote C/C++ code. They take note of what you write and ask you further questions, especially if your first solution isn’t optimal.

I tried to take extra care with my code and not let stupid mistakes creep through. I used good variable/function names, made sure my braces matched, and I ran through the algorithm on the board once I had written it.

The first interview was one of the toughest. I was more nervous. I think I made more mistakes–I didn’t see things as quickly as I did later.

I had three interviews before lunch. They then handed me off to someone else who would not be evaluating me, but would just be an escort for lunch. The Google cafeterias in Mountain View are legendary, but the Boston office is far too small to warrant such lavishness. Instead, they have a catered lunch every day. It was wonderful. They also have all the free drinks and candy you could want, available all the time. I spent much of the time asking my escort questions about Google, what he was working on (couldn’t tell me), the area, the office, the commute. We were also joined by the head of the office, who didn’t realize I was an interviewee, and we had a nice conversation as well.

Lunch was an hour, and then I was back in the conference room. I had two more interviews. Then the recruiter came back in at about 3:15 or so and debriefed me–asked me my impressions, how I felt. I reiterated what I had told him on the phone previously, and that morning before we started: that I was trying to take this as easy and nonchalantly as possible, to have fun, and learn, and let it be a good experience. I had a job that I enjoyed, and didn’t NEED this one, but I think I would do well there and enjoy it very much. They came to me, after all.

I think by the end of the day, I was really pulling that off well. Once I got over my nervousness in the first interview, I really did have fun and enjoy it.

General Notes

They didn’t ask me any stupid questions. None of this “what’s your biggest weakness?” garbage. Not even the recruiter asked me anything like that. Nothing silly at all. They also didn’t ask me easy technical questions. They got right into the problems and the code. I had to describe an algorithm for something and write code for it. It was serious, they were all nice–I met people with serious reputations online. I felt like they were respecting me as a fellow programmer–almost. I wasn’t one of them, but they really wanted to see if I could become one of them.

I did receive prompts to get through certain problems, but not overly so. I answered every question they asked. Some I answered better than others, but the ones I didn’t get right away, I had alternate solutions, and I understood where they were going as soon as they started talking about it.

Why I didn’t get the job

Well, companies these days won’t tell you why. I think they fear it opens them up to lawsuits. I think that’s silly. It prevents those of who really do want to learn and improve from knowing what we’re deficient in. Oh well. They told me that they thought I would do well at Google, but that it wasn’t a good fit at the time, and I should apply again in the future. (Of course, I didn’t apply in the first place.)

My suspicions, however, are that I lean too much towards Microsoft technologies. I do a lot of work in .Net. That’s where more and more of my experience is. I do consider myself very good in C++, but I’m doing more and more C# work. I’ve always been a Microsoft Windows developer.

I also am not really interested in web-centric technologies, and I told them so. I’m more interested in client apps on the desktop, and server apps.

Of course, it’s very possible I just didn’t answer the questions to their satisfaction–that I needed more prompting than I should have. Oh well.

It could also be that my GPA wasn’t what they wanted. I goofed off my freshman year of undergraduate work. I really hurt my grades. I came back, though, and got straight A’s for my last few years where I took the hard CS classes. I also got straight A’s in my Master’s program while I was working full time. I don’t think this was the issue, but it’s possible.

Lessons

  1. Having your own web-site is a no-brainer. Do it. Update and maintain it.
  2. Do personal projects. You must be passionate, you must love programming. You must be good at it. Not average. You must aspire to excellence and be working towards that.
  3. Know what you’re talking about it. Don’t show off–just display your knowledge as it applies to what they asked you.
  4. Use an interview with them as a learning opportunity and ensure you have a good experience regardless of the outcome.
  5. Don’t take the interview too seriously. Make sure that not everything rides on the outcome. You must be comfortable, confident. You must try for success in every possible way, but yet be completely prepared to fail–and have that be ok. This is a hard balance to achieve, but I think it can really make you have a healthy outlook and have a good time while still showing your best self.
  6. If you don’t get an offer, realize that even being selected for an on-site interview by Google puts you above the ranks of the average-good programmers. Google gets 1,500 resumes a day. You’re already in the < 1% percentile.
  7. Practice writing code by hand in a notebook. This helped more than I can express. Do stuff that’s hard that you don’t know how to do immediately. Time yourself. Make the problem more challenging. If you can’t stretch yourself, they will and you’ll probably break. They did not ask me to do any of the specific questions I had practiced–but the experience writing out and the THINKING is what helped.
  8. Be able to explain your background (90% technical / 10% personal) in a few words. At some point you’ll be asked.
  9. Have a lot of questions for people. You’re interviewing them too. Make sure they’re good questions. Asking about salary is not a good question before you’ve been made an offer.
  10. I let the interview build my own self-confidence. I have no doubt that I could walk into an interview anywhere else and it would be laughably easy.
  11. Don’t ignore obvious, simple solutions. Sometimes a table lookup is better than an O(n) algorithm.
  12. Bring a good, FUN book for the plane ride back. On the way, I focused on the interview, but on the way home I wanted to do anything but, so I had my current novel (Dickens’ Bleak House–very good book, by the way).

If you do all of those steps, it actually doesn’t really matter if you apply to Google or any other great/famous company–you’ll probably get the job you want for the pay you want anyway. Somebody, sooner or later, will come across you and give you the opportunity.

Great programmers will rarely, if ever, need to look for jobs.

I hope this long, rambling essay is helpful to some. I make no claim that my experience is typical or that I’m being completely objective. In other words, YMMV.

Read part 2 of this article

Mouse tilt wheel horizontal scrolling in C#

In my current project, I’m using a custom ListView-like control to give my WinForms app a very rich interactive experience. This control does not implement mouse wheel scrolling like the Microsoft ListView implementation does so it was up to me to add it. You can use the knowledge in this article to implement full scrolling support in your own custom controls.

The custom component was derived from Control, which does provide the virtual function OnMouseWheel to handle vertical scrolling. The component also exposes the two scrollbars to manipulate.

First, take a look at Best Practices for Supporting Microsoft Mouse and Keyboard Devices, a good place to start learning about advanced mouse handling in Windows. Note that all of this requires IntelliPoint software to be installed.

Getting Started

Here’s some example code to get started with:

public class MyListView : GlacialComponents.Controls.GlacialList 
    { 

    }

Vertical Scrolling

As long as we’re talking about horizontal scrolling, let’s go ahead and discuss vertical scrolling with the mouse wheel. Add this override to the class:

protected override void OnMouseWheel(MouseEventArgs e)
        {
            base.OnMouseWheel(e);
           
        }

It’s overriding from the Control class, not GlacialList. Assuming you’ve read the MS documentation referenced about, you’ll know that the scroll message includes the number of ticks, which is usually a multiple of 120. We need to accumulate this number and then scroll our view a corresponding amount.

First, some class variables:

        private const int WHEEL_DELTA = 120; 
        private int _wheelPos = 0; 
        private int _wheelHPos = 0;

The _wheelHPos variable will be used later for horizontal scrolling. Then we modify our function to read like this:

protected override void OnMouseWheel(MouseEventArgs e)
        {
            base.OnMouseWheel(e);

            _wheelPos += e.Delta;

            while (_wheelPos >= WHEEL_DELTA)
            {
                ScrollLine(-1);
                _wheelPos -= WHEEL_DELTA;
            }

            while (_wheelPos <= -120)
            {
                ScrollLine(1);
                _wheelPos += WHEEL_DELTA;
            }
            Refresh();
           
        }

After we accumulate the value, we scroll one line per WHEEL_DELTA value. (This code could certainly be optimized, but I think this version is clear.) After the scrolling we tell the view to refresh itself. The Best Practices recommend handling partial-line scrolling. In my case, since I just need to manipulate the scrollbars by one unit at a time it’s not applicable, but I encourage you to understand their sample code.

The ScrollLine() function will be application-dependent. For this class, it just needs to modify the scrollbars that were provided.

private void ScrollLine(int numLines) 
        { 
            vPanelScrollBar.Value = Math.Max(vPanelScrollBar.Minimum,
                             Math.Min(vPanelScrollBar.Maximum, 
                vPanelScrollBar.Value + numLines)); 
        }

Horizontal Scrolling

That was fairly easy. Horizontal scrolling with the tilt-wheel is only a little more complex. This is because it’s not natively supported by the .Net Framework, and to a certain extent it’s not really supported on Windows XP. Full native support of the tilt wheel starts in Windows Vista.

Fortunately the IntelliPoint drivers fake it for us by sending our listview window a WM_MOUSEHWHEEL message anyway. Since .Net 2.0 doesn’t know what to do with this message (not sure about .Net 3.0), we need to take control of the message-handling and manually handle this message. The WndProc function is the function that handles all of this and it is virtual just for this purpose.

protected override void WndProc(ref Message m) 
        { 
            base.WndProc(ref m); 
            if (m.HWnd != this.Handle) 
            { 
                return; 
            } 
            switch (m.Msg) 
            { 
                case Win32Messages.WM_MOUSEHWHEEL: 
                    FireMouseHWheel(m.WParam, m.LParam); 
                    m.Result = (IntPtr)1; 
                    break; 
                default: 
                    break; 

            } 
        }

If you’ve done Win32 programming this will look very familiar, if a little out of place in .Net code. There are a few things going on here. First of all, you must call the base-class version of WndProc or your window will be very unexciting and quite broken. Take a look at WndProc for any control in Reflector to see all the work it’s doing.

Next, there is the Win32Messages class. This is an abstract class of my own creation that serves merely as a place to put definitions for Windows’ message definitions.

abstract class Win32Messages 
    { 
        public const int WM_MOUSEHWHEEL = 0x020E;//discovered via Spy++ 
    }

So how did I know it was supposed to be have the value of 0x020E? Well, I could look in the Vista SDK where it’s defined, or I could read the Best Practices document referenced before. I didn’t find that page until after I had finished this implementation and I just used Spy++ to discover the messages coming to my window when I hit the tilt button:

SpyHorizTiltWheelMsg

Before we get to the FireMouseHWheel function, notice that m.Result is set to 1. This is because the docs state that the message handling must return 1 to indicate to Intellitype that we’ve handled the message.

There are two versions of this function. One takes the raw WPARAM and LPARAM values from the message and the other takes more meaningful values. As you can guess, one should probably call the other.

        public event EventHandler<MouseEventArgs> MouseHWheel; 
        protected void FireMouseHWheel(IntPtr wParam, IntPtr lParam) 
        { 
            Int32 tilt = (Int16)Utils.HIWORD(wParam); 
            Int32 keys = Utils.LOWORD(wParam); 
            Int32 x = Utils.LOWORD(lParam); 
            Int32 y = Utils.HIWORD(lParam); 

            FireMouseHWheel(MouseButtons.None, 0, x, y, tilt); 
        } 

        protected void FireMouseHWheel(MouseButtons buttons,
            int clicks, int x, int y, int delta) 
        { 
            MouseEventArgs args = new MouseEventArgs(buttons,
                                         clicks, x, y, delta); 
            OnMouseHWheel(args); 
            //let everybody else have a crack at it 
            if (MouseHWheel != null) 
            { 
                MouseHWheel(this, args); 
            } 
        }

I declare an event that takes the same type of arguments as the vertical MouseWheel handler above. The first FireMouseHWheel function converts wParam and lParam into the real values according to the specification given. I ignore the keys value and pass the others to the second function which calls my handler and also raises the event to give class consumers the opportunity to be notified as well.

To “crack” the values, I have some simple utility functions:

abstract class Utils 
    { 
        internal static Int32 HIWORD(IntPtr ptr) 
        { 
            Int32 val32 = ptr.ToInt32(); 
            return ((val32 >> 16) & 0xFFFF); 
        } 

        internal static Int32 LOWORD(IntPtr ptr) 
        { 
            Int32 val32 = ptr.ToInt32(); 
            return (val32 & 0xFFFF); 
        } 

    }

The OnMouseHWheel is very similar to its cousin for vertical scrolling:

protected virtual void OnMouseHWheel(MouseEventArgs e) 
        { 
            _wheelHPos += e.Delta; 
            const int pixelsToMove = 3; 
            while (_wheelHPos >= WHEEL_DELTA) 
            { 
                ScrollHorizontal(pixelsToMove); 
                _wheelHPos -= WHEEL_DELTA; 
            } 

            while (_wheelHPos <= -120) 
            { 
                ScrollHorizontal(-pixelsToMove); 
                _wheelHPos += WHEEL_DELTA; 
            } 
            Refresh(); 
        }

The pixelsToMove variable is noteworthy because it’s hard-coded to 3. It is kind of arbitrary because it really depends on the application and how the scrollbars are used. I’ve set it to 3 as a good value for my application.

The ScrollHorizontal function is similar to ScrollVertical and is also application-specific:

private void ScrollHorizontal(int amount) 
        { 
            hPanelScrollBar.Value = Math.Max(hPanelScrollBar.Minimum,
                   Math.Min(hPanelScrollBar.Maximum - hPanelScrollBar.mWidth, 
                hPanelScrollBar.Value + amount)); 
        }
 

Potential Issues

The Best Practices document states:

When an application receives a WM_MOUSEHWHEEL message, it is responsible for retrieving the characters-to-scroll user setting (SPI_GETWHEELSCROLLCHARS) by using the SystemParametersInfo API. This setting will not be available on Windows 2000 and Windows XP, so use the value of 1. IntelliType Pro and IntelliPoint will maintain a substitute value for the characters-to-scroll user setting and send the correct number of WM_MOUSEHWHEEL messages.

(Emphasis mine) Notice that last phrase. IntelliPoint can potentially send multiple WM_MOUSEHWHEEL messages for a single tilting action. This means that my strategy of refreshing on every message might not be entirely wise. It really depends on how long it takes to refresh the control. If it can be done smoothly and instantly, then this might not matter. Otherwise, you might need to come up with a way of accumulating ticks over multiple messages and scrolling all at once, perhaps after a timer expires. In my case, I think I’ll ignore this issue for now. I don’t really care if the control refreshes too often.

Have fun adding horizontal scrolling to your app!

Simulating a Server in .Net (C#)

I recently had a need to simulate an FTP server connection in some unit tests. Rather than developing a full test-server, for this purpose, I could easily simulate an FTP stream by creating it in memory, and then passing that stream to the functions  that expect it:

public Stream CreateTestStream(string text) { byte[] buff = Encoding.ASCII.GetBytes(text); return new MemoryStream(buff, false); }

This function merely accepts text (FTP is text-based after all), and returns a memory stream. I can then use it in a unit test:

[Test] [ExpectedException(typeof(FtpException),"InvalidResponse")] public void FtpResponse_Constructor_BadStream_InvalidCode() { using (Stream s = CreateTestStream("NoErrorCode")) { FtpResponse response = new FtpResponse(s); } }

Setting the minimum Windows version supported (C++)

Recently, I was trying to use the Shell function SHGetFolderPath. Despite including the correct header file (shlobj.h), the compiler wasn’t recognizing it. My code looked like this:

CString strPath; HRESULT hResult = SHGetFolderPath( NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, strPath.GetBufferSetLength(MAX_PATH)); strPath.ReleaseBuffer();

What I did was lookup the definition of SHGFP_TYPE_CURRENT in shlobj.h, and found this:

#if (NTDDI_VERSION >= NTDDI_WIN2K) SHSTDAPI_(void) SHFlushSFCache(void); typedef enum { SHGFP_TYPE_CURRENT = 0, // current value for user, verify it exists SHGFP_TYPE_DEFAULT = 1, // default value, may not exist } SHGFP_TYPE; SHFOLDERAPI SHGetFolderPathA(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, __out_ecount(MAX_PATH) LPSTR pszPath); SHFOLDERAPI SHGetFolderPathW(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, __out_ecount(MAX_PATH) LPWSTR pszPath); //etc...

It’s that first line that got me. My DDI version wasn’t >= that of Win2k’s. The solution is to modify the stdafx.h file. Before, it read:

#ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0400 #endif

That 0x0400 defines Windows 95 as the minimum supported OS. I don’t really care about 9x support, so I changed it to read like this:

#ifndef _WIN32_WINNT //define Windows 2000 as minimum necessary OS #define _WIN32_WINNT 0x0500 #endif