2010-12-17 12 views

Odpowiedz

11

Od MSDN:

wParam
Ten parametr nie jest używany.

lParam
Słowo bajtu wskazuje współrzędnej x kursora. Współrzędna jest odniesiona do górnego lewego rogu ekranu .
Słowo wyższego rzędu określa współrzędną y kursora. Współrzędna jest odniesiona do górnego lewego rogu ekranu .

Więc po prostu trzeba wyodrębnić niskiego rzędu i wyższego rzędu słów komunikat na lParam:

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

nie będę się zbytnio obawiać o wydajność, ponieważ te operacje są tylko na poziomie nieco arytmetyka ...

Należy zauważyć, że te współrzędne odnoszą się do ekranu. Jeśli chcesz współrzędnych w stosunku do kontroli (lub formy), można użyć metody PointToClient:

Point relativePos = theControl.PointToClient(pos); 
+0

Działa doskonale! Dziękuję bardzo! – Vercas

+2

Rozważ oglądnięcie następnej odpowiedzi. TL; DR, prześlij 'x' i' y' na '(short)' przed przypisaniem ich do obsługi konfiguracji wielu monitorów (które mają ujemne współrzędne). – Gman

12

Aż do rana, bym zgodził się w 100% z Thomas Levesques odpowiedź, wyciągnąłem te same informacje od msdn i kod (pozornie) działał idealnie. Jednak jest jeden przypadek, w którym to cię ugryzie, zajęło mi trzy godziny, aby znaleźć powód dzisiejszego popołudnia.

Symptomem było to, że na jednej z moich maszyn programistycznych w IDS VS2010, moja kontrola była możliwa do wyboru tylko przez kliknięcie, gdy kliknąłem na niej w określonej pozycji y. Bardzo małych formantów u góry formularza nie można było wybrać, klikając w ogóle. Rozmiar regionu, który nie był klikalny, wyglądał identycznie jak rozmiar IDE otaczającego projektanta Windows Forms, więc na początku myślałem, że mam jakiś dziwny, mało znany problem DesignMode. Najbardziej mylące było to, że dokładnie ten sam projekt (sprawdzony z TFS na innej maszynie) nie pokazywałby takiego zachowania.

Oto co się dzieje:

Rozważyć masz podwójną konfigurację monitora, jak pokazano tutaj (przepraszam za niemieckiego zrzucie, nie mają systemowe pod ręką):

Double monitor setup

Jak widać, górny lewy róg monitora 2 ma współrzędne (1280, -256). Jeśli użyjesz rozwiązania pokazanego powyżej, uzyskasz wartość równą 65505, jeśli mysz naprawdę jest w -30. Dzieje się tak dlatego, że pozycje są przechowywane jako wysokie i niskie zamówienie WORD z LParam. Tak więc, wykonanie (lParam.ToInt32() & 0xFFFF0000) >> 16 da ci właściwe bity dla pozycji y. Przesyłanie tego do int daje jednak 65505, ponieważ przenosisz do niewłaściwego typu danych.

Rozwiązanie:

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

Casting do short daje poprawne wartości pozycji. Również rzuciłem X, ponieważ możesz ustawić monitory w taki sposób, że drugi monitor pozostaje z głównego, a zatem pozycja x miałaby ten sam problem.

Ostatnio odkryłem, że jeden z konstruktorów z Point trafi do pracy za Ciebie. Więc krótka wersja jest:

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

Mam 2 monitory (wiele monitorów FTW!) I mam zamiar przyjrzeć się temu. Byłby to ogromny problem dla użytkowników. – Vercas

+0

@Vercas Proszę. Ciekaw jestem, czy moja konfiguracja jest tak niezwykła, ponieważ nigdy nie widziałem tego wzmiankowanego gdzie indziej i naprawdę nie mogę sobie wyobrazić, że tylko ja to widzę. W każdym razie, dwa monitory mogą być ułożone w taki sposób, że tak się nie dzieje, jeśli są tego samego rozmiaru i orientacji i rozmieszczone od lewej do prawej, otrzymasz jedną dużą płaszczyznę (w moim przykładzie) 2560x1024px. Ponieważ nie ma żadnych ujemnych współrzędnych w żadnej z pozycji monitora, nie będzie to problemem. Co ciekawe, tylko drugi obróciłem mój drugi monitor w ten sposób wczoraj :) – takrl

+0

Tak, jestem pewien, że jest to dokładny problem, że makra "GET_X_LPARAM" i "GET_Y_LPARAM" zostały dodane do adresu, gdy system Windows uzyskał wsparcie dla wielu monitorów (około 98). Nie powinieneś dalej używać makr "LOWORD" i "HIWORD". (Oczywiście ta makro-głupota musi zostać przetłumaczona na .NET, ale pomyślałem, że wyjaśnienie było przydatne.) –

7

Wiem, że to pytanie zostało już odpowiedział i wszystko, ale ...

Point p = new Point(m.LParam.ToInt32()); 

System.Drawing.Point ma teraz konstruktor specjalnie zaprojektowany, aby przyjąć tę wartość dokładnie . Ściśle mówiąc, myślę, że jest to prawdopodobnie najłatwiejszy sposób na uzyskanie .

Szczerze mówiąc, nie mam pojęcia, czy ten konstruktor istniał nawet po opublikowaniu innych odpowiedzi.

To wszystko, co jest powiedziane, prawdopodobnie nie jest to żadna szybsza ponieważ odpowiedź takrl jest prawie na pewno to, co wyżej wspomnianego konstruktora wewnętrznie.

Powiązane problemy