Entwickler-Ecke

Windows API - Mauswheel - Drehrichtung


M. Raab - Do 29.05.03 15:52
Titel: Mauswheel - Drehrichtung
Hallo NG,


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
function WndProc(hWnd: HWND; Msg: UINT;  wParam: WPARAM;  lParam: LPARAM): LRESULT; stdcall;
begin
  case (Msg) of
    WM_MOUSEWHEEL:
      begin
        if HIWORD(wParam) > 0 then
          begin
            skalar:=skalar - 0.05;             // WHEEL_DELTA;
            if skalar<0.5 then skalar:=0.5;
            form1.normierung;
            result:=0;
          end else begin
            skalar:=skalar + 0.05;           // WHEEL_DELTA;
            form1.normierung;
            result:=0;
          end;

      end;

Mit o.g. Code bestimme ich, in welchse Richtung das Mausrad gedreht wird. Seit ich im Compiler die Bereichsprüfung aktiviert habe (DELPHI 7) erscheint nun eine Fehlermeldung, dass eine Bereichsüberschreitung vorliegen würde. Grund hierfür scheint mir zu sein, dass wParam negativ wird. Kann mir jemand helfen ? Ich könnte den Compilerschalter wieder deaktivieren und dann klappt alles wieder - ich möchte jedoch den Grund erfahren .... :?:


Gruss


Markus


w3seek - Fr 30.05.03 11:53

welcher typ ist skalar?


MaxiTB - Fr 30.05.03 13:30

Hm - WPARAM ist ein unsigned int32 - also auf Delphisch ein Cardinal.

Cardinals können gar nicht negativ werden ... also mutet mir das ganze ein bisserl komisch an ...


w3seek - Sa 31.05.03 01:09

evtl funktioniert das hier indem du den HiWord zu einem signed word (smallint) konvertierst (in einem aelteren Projekt von mir hat das jedenfalls funktioniert und in der psdk steht glaube ich ein beispiel das genau so arbeitet):


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
function WndProc(hWnd: HWND; Msg: UINT;  wParam: WPARAM;  lParam: LPARAM): LRESULT; stdcall;
var
  wDelta: Smallint;
begin
  case (Msg) of
    WM_MOUSEWHEEL:
      begin
        wDelta := HIWORD(wParam);
        if wDelta > 0 then
          begin
            skalar:=skalar - 0.05;             // WHEEL_DELTA;
            if skalar<0.5 then skalar:=0.5;
            form1.normierung;
            result:=0;
          end else begin
            skalar:=skalar + 0.05;           // WHEEL_DELTA;
            form1.normierung;
            result:=0;
          end;
      end;


M. Raab - Sa 31.05.03 10:56

Hallo NG,

nö, hilft nicht. Wie schon gesagt: wenn ich bei den Compilerschaltern die Bereichsprüfung ausschalte, kalppt es wieder. Ansonsten kommt sofort eine Meldung: Bereichsprüfung Fehler.

Aber die Lösung war:




Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
function WndProc(hWnd: HWND; Msg: UINT;  wParam: WPARAM;  lParam: LPARAM): LRESULT; stdcall;
Var wDelta : Longint;
begin
  case (Msg) of
    WM_MOUSEWHEEL:
      begin
        wDelta := wParam;
        if wDelta > 0 then
          begin
            skalar:=skalar - 0.05; // WHEEL_DELTA;
            if skalar<0.5 then skalar:=0.5;
            form1.normierung;
            result:=0;
          end else begin
            skalar:=skalar + 0.05;  // WHEEL_DELTA;
            form1.normierung;
            result:=0;
          end;

      end;



Es ist offenbar so, dass DELPHI 7 empfindlicher reagiert als DELPHI 5. Dort hat dieser Code nämlich problemlos funktioniert. Mit dem Wechsel auf DELPHI 7 und diesen Compilerschaltern gab es dieses Problem.

Nun ja, es klappt.

Gruss und Vielen Dank


Markus


w3seek - Sa 31.05.03 11:35

kommt die Warnung/Hinweis auch bei wDelta := Longint(wParam);


M. Raab - So 01.06.03 09:52

Hallo,


so funzt es auch:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
function WndProc(hWnd: HWND; Msg: UINT;  wParam: WPARAM;  lParam: LPARAM): LRESULT; stdcall;
//Var wDelta : Longint;
begin
  case (Msg) of
    WM_MOUSEWHEEL:
      begin
//        wDelta := wParam;
        if longint(wParam) > 0 then
          begin
            skalar:=skalar - 0.05// WHEEL_DELTA;
            if skalar<0.5 then skalar:=0.5;
            form1.normierung;
            result:=0;
          end else begin
            skalar:=skalar + 0.05;  // WHEEL_DELTA;
            form1.normierung;
            result:=0;
          end;

      end;

Also mit LongInt(WParam) klappt das ganze auch - wie schon gesagt. Deaktiviert man die Berechsprüfung im Compiler, scheint es kein Problem zu sein, dass das negativ werden kann. Vielleicht ist das Ganze auch ein Bug von DELPHI 7. :?: :?:


Gruss

Markus


MaxiTB - Mo 02.06.03 10:46
Titel: Kleiner theoretischer Exkurs
Gegeben sei eine nette Standard-WinProc:


Quelltext
1:
function WndProc(hWnd: HWND; Msg: UINT;  wParam: WPARAM;  lParam: LPARAM): LRESULT; stdcall;                    


Nun weiß man, daß sowohl wParam wie auch lParam vorzeichenlose Zahlen sind.

Nun sehen wir uns das mal an:


Quelltext
1:
if wParam > 0 then                    


Was will uns dieser Code sagen ?

Tja - unter C käme die nette Meldung 'Condition always true' (wenn >= verwendet würde).
Wie kann auch eine vorzeichenlose Zahl jemals negativ werden ? - Also stimmt die Bedingung nur bei 0 nicht ... sozusagen ist das ganze Müll. *g*

Klar werden die einen sagen, vorzeichenlose, vorzeichenbehaftet - 2er Kompliment machts möglich und eigentlich Wurscht.

Das scheint falsch zu sein, sonst würde der D7-Compiler nicht so empfindlich darauf reagieren (sollte man sich den Assembercode mal ansehen, was da intern bei sowas passiert).

Wiefe Leute haben einen type-cast gesetzt - so nach dem Motto:


Quelltext
1:
if longint(wParam) > 0 then                    


Aber ist das so fein ?
Hm - meines Achtens sehr gefährlich die Sache oder besser unhübsch. Ein type-cast kann ebenfalls sehr suspekt sein ... also warum nicht gleich auf die hübsche Weise ...


Quelltext
1:
if not (wParam and $80000000) then                    


Das ist
a) das selbe ...
b) sagt mehr aus (meiner Meinung - wenn das HSB high, dann negativ) ...
c) es ist transparent.

Fazit: Interessantes Thema zum Fachsimplen, besonders da ja sogar der obrige Code Maschinen- und OS-abhängig ist - aber eh, das ist die WinProc von sich aus (man denke nur an die 16Bit/32Bit Umstellung). Also wenn ein 64Bit Windows kommt, dann muß man die Funktion sowieso umstellen (schon alleine wegen der WinProc das Programm mindestens neu programmieren).


M. Raab - Do 05.06.03 11:37

Hallo,

ist wirklich ne akademische Diskussion - aber unsauber programmiert. DELPHI 5 war da tolleranter und hat den Cardinal also anders behandelt: mit nem Vorzeichen. Der Witz war aber, dass der Code bei ausgeschalteter Bereichsprüfung funzt.

Nun ja..... :?: :idea:


Danke an A L L E !!


Gruss


Markus