Window Callback Verständnisfragen

Anfängerfragen zum Programmieren mit PureBasic.
Jake
Beiträge: 121
Registriert: 28.05.2005 04:10
Wohnort: Berlin

Window Callback Verständnisfragen

Beitrag von Jake »

Ich habe mir einen Window Callback aus dem Forum rausgesucht den ich gerade brauche. Stand in einem Post von hallodri und ich habe ein bischer daran geändert.

Code: Alles auswählen

Procedure Callback(hwnd, msg, wParam, lParam)
	Result = #PB_ProcessPureBasicEvents
	Select msg
		Case #WM_COMMAND
			Select ((wParam>>16) & $FFFF)
				Case #CBN_SELCHANGE
					Select EventGadgetID()
						Case #SearchState
							Search()
					ProcedureReturn 0
					EndSelect
			EndSelect
	EndSelect
	ProcedureReturn Result
EndProcedure
Nun zu meinen Fragen:

1. Warum wir das gemacht [c]wParam>>16[/c]?
Das verschiebt doch das wParam dorthin wo das lParam steht? Wenn ja warum?


2. Der Rest ist mir völlig unklar [c]& $FFFF[/c]
Ein Binärwert von z.B. $F=1111 bitweise mit einem [c]beliebigen Binärwert[/c] verknüpft, ergibt doch immer den [c]beliebigen Binärwert[/c]?

3. Wo ist der Unterschied bei den Rückgabewerten bzw. deren Auswirkungen. [c](ProcedureReturn 0, ProcedureReturn #PB_ProcessPureBasicEvents)[/c]

4. Ist es in Ordnung das ich in einem Callback [c]Select EventGadgetID()[/c] verwende oder ist das unsauber?
MfG Jake
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Er ermittelt das HighWord aus dem Long
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Re: Window Callback Verständnisfragen

Beitrag von edel »

MSDN hat geschrieben:The WM_COMMAND message is sent when the user selects a command item from a menu, when a control sends a notification message to its parent window, or when an accelerator keystroke is translated.

Syntax

WM_COMMAND

WPARAM wParam
LPARAM lParam;

Parameters

wParam
The high-order word specifies the notification code if the message is from a control. If the message is from an accelerator, this value is 1. If the message is from a menu, this value is zero.
The low-order word specifies the identifier of the menu item, control, or accelerator.

lParam
Handle to the control sending the message if the message is from a control. Otherwise, this parameter is NULL.

Return Value

If an application processes this message, it should return zero.
"The low-order word specifies the identifier of the menu
item, control, or accelerator. " heisst in diesem Fall die GadgetID

http://msdn.microsoft.com/library/defau ... ommand.asp


So wuerd ich es wohl selber machen :

Code: Alles auswählen

Procedure HIWORD(Value)
  ProcedureReturn (Value >> 16) & $FFFF
EndProcedure

Procedure LOWORD(Value)
  ProcedureReturn Value & $FFFF
EndProcedure

Procedure Callback(hwnd, msg, wParam, lParam)
  result = #PB_ProcessPureBasicEvents
  
  Select msg
    Case #WM_COMMAND
      Select HIWORD(wParam)
        Case #CBN_SELCHANGE
          Select LOWORD(wParam)
            Case #SearchState
              Debug "Search()"
              ProcedureReturn 0
          EndSelect
      EndSelect
  EndSelect
  
  ProcedureReturn result
  
EndProcedure



Normalerweise wird am Ende das Ergebnis von CallWindowProc_(altercallback,hwnd,msg,wParam,lParam),
mit allen Werten zurueck an den urspruenglichen Callback gegeben.
Wenn dein Callback die Message verarbeitet hat , braucht der alte
Callback sich (meistens) nicht mehr darum zu kuemmern und es
wird der auf z.b. MSDN (Link oben) angegebene Wert zurueck-
gegeben (Ich hoffe ich habe Danilo damals richtig verstanden).
Ich vermute mal das PB_ProcessPureBasicEvents bei Rueckgabe
nur ein Flag ist, das den alten Callback sagt ob es die Message nun
verarbeiten soll oder nicht .
Benutzeravatar
Falko
Admin
Beiträge: 3535
Registriert: 29.08.2004 11:27
Computerausstattung: PC: MSI-Z590-GC; 32GB-DDR4, ICore9; 2TB M2 + 2x3TB-SATA2 HDD; Intel ICore9 @ 3600MHZ (Win11 Pro. 64-Bit),
Acer Aspire E15 (Win11 Home X64). Purebasic LTS 6.11b1
HP255G8 Notebook @AMD Ryzen 5 5500U with Radeon Graphics 2.10 GHz 3.4GHz, 32GB_RAM, 3TB_SSD (Win11 Pro 64-Bit)
Kontaktdaten:

Beitrag von Falko »

Na ich glaube, ihm ging es mehr um das LoWord bzw. HiWord, welches aus
den beiden Longwerten LParam bzw. WParam aus diesen ausgelesen wird,
was man im ersten Blick daraus nicht verstehen kann.

[Edit] Soweit ich weis, wird nur in dem Longwert wParam eine
Bitverschiebung gemacht und nichts wird im lParam hinein
geschoben.
Quasi werden dabei die 16Bits, die hinten herausfallen gelöscht und am
Anfang wieder 16 Nullen aufgefüllt und durch die
AND-Verknüpfung (& $FFFF) filtere ich das LoWord.

Man möge mir verzeihen, wenn ich das jetzt nicht genau beschrieben habe :roll:
Sollte da noch was falsch sein bzw. fehlen, bitte ich um eure Korrektur.
[/Edit]

Darum die obige Schreibform.

0 & 1 = 0 , siehe in der Hilfe unter Variablen.
Verknüpfung binäre & (AND) aus der PB-Hilfe hat geschrieben:LS | RS | Ergebnis
---------------------
0 | 0 | 0
0 | 1 | 0
1 | 0 | 0
1 | 1 | 1
Beispiel:
Ich habe vorhin in einem VB-Beispiel gefunden, welches dieses anders
macht und vielleicht verständlicher aussieht.

Vielleicht kann man's gebrauchen.
Wegen der Geschwindigkeit ist das Obige vorzuziehen.


Code: Alles auswählen

Procedure.s LoWord(nDWORD.l)
    Result.s=Left(Right("00000000" +  Hex(nDWORD),8),4)
    ProcedureReturn Result
EndProcedure

Procedure.s HiWord(nDWORD.l)
 Result.s=Right(Right("00000000" +  Hex(nDWORD),8),4)
 ProcedureReturn Result
EndProcedure

Procedure.s LoByte(nDByte.w)
    Result.s=Left(Right("0000000" +  Hex(nDByte),4),2)
    ProcedureReturn Result
EndProcedure

Procedure.s HiByte(nDByte.w)
    Result.s=Right(Right("0000000" +  Hex(nDByte),4),2)
    ProcedureReturn Result
EndProcedure


Debug LoWord(%00000000000000001111111111111111)+"     "+  HiWord (%00000000000000001111111111111111)
Debug LoWord(%11111111111111110000000000000000)+"     "+  HIWord(%11111111111111110000000000000000)

Debug LoByte(%0000000011111111) +"    "+ HiByte(%0000000011111111)
Debug LoByte(%1111111100000000) +"    "+ HiByte(%1111111100000000)
Bild
Win11 Pro 64-Bit, PB_6.11b1
Jake
Beiträge: 121
Registriert: 28.05.2005 04:10
Wohnort: Berlin

Beitrag von Jake »

Danke, ihr liegt da beide richtig. Ist mir einfach alles unklar und hat mir beides gehlofen.

Erstmal hatte ich da was verwechselt. Habe HighWord mit wParam und LowWord mit lParam gleichgesetzt was ja nichts miteinander zu tun hat, wie ich aus euren Posts ersehen konnte.

@hallodri
Das mit dem Filtern der GadgetID aus dem lParam geht gut so erspare ich mir eine Fehlermeldung bzw. ein IsGadget.

Die Rückgabe von ProcedureReturn ist mir nun auch klar.

Code: Alles auswählen

Return Value

If an application processes this message, it should return zero. 
Steht bei der Message in der MSDN bzw. PSDK. Nun weis ich endlich wozu das da steht, hab ich mich schon öffter gefragt.
Und wenn #PB_ProcessPureBasicEvents zurückgegeben wird, macht das nicht der Callback sonder PB mit seinen Events.
So hast du das doch gemeint.


@Falko
Ok das mit dem Verschieben ist klar. Nur wozu die logische UND-Verknüpfung nötig ist leuchtet mir nicht ein.

Code: Alles auswählen

$00BC    = 0000000010111100
$FFFF    = 1111111111111111
---------------------------
Ergebnis = 0000000010111100
Hier kann man sehen das bei einer UND-Verknüpfung mit F immer das selbe drin steht wie vorher auch.
Ich habe daraufhin folgende Zeilen in meinen Callback eingebaut:

Code: Alles auswählen

Debug (wParam>>16)
Debug((wParam>>16) & $FFFF)
In beiden Fällen steht das selbe im Debugger-Fenster. Jedoch funktioniert der Callback nur mit [c]((wParam>>16) & $FFFF)[/c].
Wenn das noch geklärt wird bin ich :).
MfG Jake
Benutzeravatar
Falko
Admin
Beiträge: 3535
Registriert: 29.08.2004 11:27
Computerausstattung: PC: MSI-Z590-GC; 32GB-DDR4, ICore9; 2TB M2 + 2x3TB-SATA2 HDD; Intel ICore9 @ 3600MHZ (Win11 Pro. 64-Bit),
Acer Aspire E15 (Win11 Home X64). Purebasic LTS 6.11b1
HP255G8 Notebook @AMD Ryzen 5 5500U with Radeon Graphics 2.10 GHz 3.4GHz, 32GB_RAM, 3TB_SSD (Win11 Pro 64-Bit)
Kontaktdaten:

Beitrag von Falko »

Du musst von einem Longwert (32Bits) ausgehen. Damit du das linke Word (16Bit ) erhältst, schiebst du ja das HiWord von links nach rechts um genau 16 Bits. Du hast immer noch ein Longwert. Jetzt willst du aber das Word aus diesem Wert auslesen. Dazu benutzt du einen Filter als Word um von rechts nach links diese 16 Bits zu bekommen.

Hier ein Beispiel. Wie das dann aussieht, wenn man es weg lassen würde, bzw. mit $FFFF so lässt.

Code: Alles auswählen

My_Long.l=$F000FFFF ; Der Longwert, der z.B. auch in lParam stehen könnte
Debug Bin(My_Long)+ "                  Der Longwert im Usprung"
My_Word.s=Bin(((My_Long)>>16)); hier steht immer noch ein Longwert
Debug My_Word + "                  Hier nach der Verschiebung nach rechts"
My_Word.s=Bin(((My_Long)>>16) & $FFFF); hier lese ich nur die 16 niederwertigen Bits von rechts nach links aus (entspricht ein Word)
Debug My_Word + "                  Und hier das ausgelesene Word (16Bits)von rechts nach links"
11110000000000001111111111111111 Der Longwert im Usprung
11111111111111111111000000000000 Hier nach der Verschiebung nach rechts
1111000000000000 Und hier das ausgelesene Word (16Bits)von rechts nach links
Gruss Falko
Zuletzt geändert von Falko am 15.12.2005 16:17, insgesamt 1-mal geändert.
Bild
Win11 Pro 64-Bit, PB_6.11b1
Jake
Beiträge: 121
Registriert: 28.05.2005 04:10
Wohnort: Berlin

Beitrag von Jake »

Jetzt ist alles klar. Fall abgeschlossen sozusagen.

Danke nochmal.
MfG Jake
Benutzeravatar
helpy
Beiträge: 636
Registriert: 29.08.2004 13:29

Beitrag von helpy »

Falko hat geschrieben:

Code: Alles auswählen

My_Long.l=$F000FFFF ; Der Longwert, der z.B. auch in lParam stehen könnte
Debug Bin(My_Long)+ "                  Der Longwert im Usprung"
My_Word.s=Bin(((My_Long)>>16)); hier steht immer noch ein Longwert
Debug My_Word + "                  Hier nach der Verschiebung nach rechts"
My_Word.s=Bin(((My_Long)>>16) & $FFFF); hier lese ich nur die 16 niederwertigen Bits von rechts nach links aus (entspricht ein Word)
Debug My_Word + "                  Und hier das ausgelesene Word (16Bits)von rechts nach links"
11110000000000001111111111111111 Der Longwert im Usprung
11111111111111111111000000000000 Hier nach der Verschiebung nach rechts
1111000000000000 Und hier das ausgelesene Word (16Bits)von rechts nach links
Hi Falko,

Jetzt hab' ich auch noch mal was gelernt!

Wenn man also eine Variable vom Typ LONG &-Verknüpft mit einer Konstanten $FFFF, dann erfolgt sozusagen zusätzlich zur &-Verknüpfung eine Datentyp-Umwandlung nach WORD (so mein erster aber nicht richtiger Gedankengang).

Da hab' ich dann folgenden Test versucht:

Code: Alles auswählen

#aWordConstant = $FFFF
aWordVariable.w = #aWordConstant
aLongVariable.l = #aWordConstant
Debug Bin(aWordVariable)
Debug Bin(aLongVariable)
Debug Bin(#aWordConstant)
Debug Bin($FFFF)
Ergebnis:

Code: Alles auswählen

11111111111111111111111111111111        ... aWordVariable
1111111111111111                        ... aLongVariable
1111111111111111                        ... #aWordConstant
1111111111111111                        ... $FFFF
Logisch nachvollziehbar ist dieses Ergebnis auf den ersten Blick nicht für mich.

Nach etwas grübeln, hat es dann klick gemacht:
Wenn man sich das ganze aber nicht von den HEX-Werten her ansieht, sondern bedenkt, dass alle Werte vor der Berechnung in eine Zahl vom Datentyp LONG umgerechnet werden, dann verstehe ich die Ergebnisse, denn die Funktion Bin() gibt keine führenden Nullen aus!

cu, helpy
Benutzeravatar
Falko
Admin
Beiträge: 3535
Registriert: 29.08.2004 11:27
Computerausstattung: PC: MSI-Z590-GC; 32GB-DDR4, ICore9; 2TB M2 + 2x3TB-SATA2 HDD; Intel ICore9 @ 3600MHZ (Win11 Pro. 64-Bit),
Acer Aspire E15 (Win11 Home X64). Purebasic LTS 6.11b1
HP255G8 Notebook @AMD Ryzen 5 5500U with Radeon Graphics 2.10 GHz 3.4GHz, 32GB_RAM, 3TB_SSD (Win11 Pro 64-Bit)
Kontaktdaten:

Beitrag von Falko »

@helpy, das mit dem Bin() stimmt leider. Ich hätte ja auch den RSet() benutzen können um die fehlenden Nullen am Anfang anzuzeigen. :)
In GFA-Basic ist das etwas besser mit dem Befehl: BIN$(Wert,[n])
Dann erhalte ich automatisch die führenden Nullen, wenn dort welche sind :mrgreen:
[Edit]
Vielleicht hätte Fred ja einen ASM Rotierbefehl in PB einbauen können

Code: Alles auswählen

; Rotierbefehle in ASM, bitte dazu ASM-Unterstützung in den Compilereinstellungen einschalten
Procedure.l Rotate_Left(Wert.l)
    MOV eax,  Wert
    RCL eax,16
    ProcedureReturn  ; Der zurückgegebene Wert wird 45 sein
  EndProcedure
  
  Procedure.l Rotate_Right(Wert.l)
    MOV eax,  Wert
    RCR eax,16
    ProcedureReturn  ; Der zurückgegebene Wert wird 45 sein
  EndProcedure
  
Debug Bin(Rotate_Left(%10101010101010101111111111111111))

Debug Bin(Rotate_Left(%11111111111111111010101010101010))
[/Edit]

Gruss Falko
Bild
Win11 Pro 64-Bit, PB_6.11b1
Antworten