Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

How do I get the coordinates of a WM_NCHITTEST message in C# code?
I'd love to get the fastest way, because performance is a requirement.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
273 views
Welcome To Ask or Share your Answers For Others

1 Answer

Up until this morning, I'd have agreed 100% with Thomas Levesques answer, I pulled the same information from msdn and the code (seemingly) worked perfectly. However, there's one case where this will bite you, it took me three hours to find the reason this afternoon.

The symptom I had was that, on one of my development machines, within the VS2010 IDE, my control was only selectable by clicking when I clicked on it at a certain y-position. Very small controls at the top of the form weren't selectable by click at all. The size of the region that wasn't clickable looked identical to the size of the IDE surrounding the Windows Forms designer, so at first I thought I had some weird little-known DesignMode problem. The most confusing bit was that exactly the same project (checked out of TFS on a different machine) wouldn't show this behavior.

Here's what happens:

Consider you have a double monitor setup as shown here (sorry for the german screenshot, I don't have an english OS at hand):

Double monitor setup

As you can see, the upper left corner of monitor 2 is at coordinates (1280, -256). If you use the solution shown above, you'll get an y of something like 65505 if the mouse really is at -30. This is because the positions are stored as high and low order WORD of LParam. So, doing (lParam.ToInt32() & 0xFFFF0000) >> 16 will give you the correct bits for the y-position. Casting this to int, however, yields 65505 since you're casting to the wrong data type.

Solution:

int x = (short)(lParam.ToInt32() & 0x0000FFFF);
int y = (short)((lParam.ToInt32() & 0xFFFF0000) >> 16);
Point pos = new Point(x, y);

Casting to short gives you the correct position values. I did cast the x as well, since you can arrange your monitors in a way that the second monitor is left of the main one, and hence the x-position would have the same problem.

I recently found that one of the constructors of Point will to the work for you. So, the short version is:

Point pos = new Point(lParam.ToInt32());

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...