SetWindowLong_() zerstört Menü-Ereignisse

Windowsspezifisches Forum , API ,..
Beiträge, die plattformübergreifend sind, gehören ins 'Allgemein'-Forum.
BillTuer
Beiträge: 2
Registriert: 02.02.2015 21:58

SetWindowLong_() zerstört Menü-Ereignisse

Beitrag von BillTuer »

SetWindowLong_() zerstört Menü-Ereignisse

Hallo zusammen,
  • Um welche Art von Problem handelt es sich:
Prozedurzeiger-Problem?
  • Kurzbeschreibung:
Menu-Bar und Popup-Menu werden nach dem aufrufen des „SetWindowLong_()“-Befehls, nicht richtig ausgewertet und verarbeitet.
  • Welche äußeren Umstände lösen das Problem aus?
Weiß nicht, alles was mir eingefallen ist hab ich ausprobiert.
  • Kurze Schritt-für-Schritt-Beschreibung wie man das Problem reproduzieren kann:
Erstellen einer neuen Callback-Prozedur, eines Fenster, eines MenüBars und eines Popup-Menüs
Aufrufen des Befehls SetWindowLong_(), und Callback auf neue Prozedur setzen, Rückgabewert merken
Wenn das Callback von der API aufgerufen wird, ausführen des Befehls CallWindowProc_() mit dem gemerktem Rückgabewert.
  • Welches Verhalten habe ich erwartet:
Wenn ich innerhalb des Callbacks die Funktion CallWindowProc_() oder CallFunctionFast() aufrufe, hätte ich eigentlich erwartet
das die Menüs funktionieren, da ich die vorher gesetzten Prozeduren ja aufrufe!
  • Ausführliche Beschreibung:
Ich haben in den letzten Tagen ein neues Projekt begonnen. In diesem geht es zum jetzigen Zeitpunkt darum, von einer DLL aus auf einem fremden PanelGadget einen weiteren Tab zu erstellen und
dann mit weiteren diversen Gadgets und Popup-Menüs zu befüllen. Nachdem ich nun die neuen Tabs, die Gadgets und Popup-Menüs hinzugefügt habe, musste ich
um die Ereignisse der Popup-Menüs zu werten ein neues Callback setzen (funktioniert irgendwie mit BindMenuEvent() irgendwie nicht).

Nach dem ich allerdings ein SetWindowLong_() gesetzt habe, musste ich feststellen das dass Menü des Hauptfensters nicht mehr Funktioniert.
Auch wenn ich im Callback die vorher gemerkte Prozedur (die von SetWindowLong_() zurückgeben wird) durch ein CallWindowProc_() aufrufe passiert nichts!.
Benutze ich ein weiteres Mal SetWindowLong_(), direkt nach dem ersten, mit dem Rückgabewert des ersten Aufrufs funktioniert alles wieder.
  • Aktuelles System
OS: Windows 7, Windows 8.1, Ubuntu und Debian
PB-Version: PureBasic 5.31 x86 & x64
Prozessor: Intel i7 x64

Einen Beispiel Code habe ich unten Bereit gestellt, dieser stammt zwar nicht meinem Projekt hat aber das gleiche Problem.
Ich hoffe das jemand von Euch einen Tipp hat, was ich falsch mache.

Danke im voraus
BillTuer

Code: Alles auswählen

Global *OldProc, usedHWND.i

Procedure myWNDProc(hwnd, uMsg,  lParam, wParam)
	Result = #PB_ProcessPureBasicEvents
	Delay(1)
	
	If hWND = usedHWND
		If uMSG = #WM_MENUSELECT
			DrawMenuBar_(hwnd)
		EndIf
		
		;Ganz egal wie ich die gespeicherte Funktion auch aufrufe 
		;der effekt bleibt der gleiche. Die MenuBar und das Popup-Menü
		;funktionieren nicht
		
		CallFunctionFast(*OldProc, hwnd, uMsg, lParam, wParam)
		CallWindowProc_(*OldProc, hwnd, uMsg, lParam, wParam)
		DefWindowProc_(hwnd, uMsg, lParam, wParam)
		
		;ProcedureReturn Result
	EndIf
EndProcedure

;Ein Popup-Menü erstellen
If CreatePopupMenu(1)
	MenuItem(100, "Cut")
	MenuItem(120, "Copy")
	MenuItem(130, "Paste")
	MenuBar()
	OpenSubMenu("Options")
	MenuItem(140, "Window...")
	MenuItem(150, "Gadget...")
	CloseSubMenu()
	MenuBar()
	MenuItem( 160, "Quit")
EndIf


If OpenWindow(0, 100, 150, 195, 260, "PureBasic - Menu")
	
	;Eine MenuBar erstellen 
	If CreateMenu(0, WindowID(0))
		MenuTitle("File")
			MenuItem( 1, "&Load...")
			MenuItem( 2, "Save")
			MenuItem( 3, "Save As...")
			MenuBar()
			
			OpenSubMenu("Recents")
				MenuItem( 5, "Pure.png")
				MenuItem( 6, "Basic.jpg")
				
				OpenSubMenu("Even more !")
					MenuItem( 12, "Yeah")
				CloseSubMenu()
				
				MenuItem( 13, "Rocks.tga")
			CloseSubMenu()
			
			MenuBar()
			MenuItem( 7, "&Quit")
		
		MenuTitle("Edition")
			MenuItem( 8, "Cut")
			MenuItem( 9, "Copy")
			MenuItem(10, "Paste")
		
		MenuTitle("?")
			MenuItem(11, "About")
		
	EndIf
	
	;Ein paar MenuItems deaktivieren
	DisableMenuItem(0, 3, 1)
	DisableMenuItem(0, 13, 1)
	
	;Ein paar Gadgets erstellen
	ListIconGadget(0, 10, 10, 280, 240, "Tools", 200)
	AddGadgetItem(0, -1, "Hammer")
	AddGadgetItem(0, -1, "Screwdriver")
	
	;Setzen des neuen WindowCallbacks, ist auch egal ob ich die Funktion
	;SetWindowLong_() oder SetWindowLongPtr_() benutze, die Menüs Funktionieren
	;nicht.
	;Benutze ich einen weiteren Aufruf von SetWindowLong(), mit *OldProc als
	;dwNewLong()-Parameter funktioniert alles wieder.
	usedHWND = WindowID(0)
	*OldProc = SetWindowLong_(WindowID(0), #GWL_WNDPROC, @myWNDProc())
	;SetWindowLong_(WindowID(0), #GWL_WNDPROC, *OldProc)
	
	
	;Ereigniss-Schleife starten
	Repeat
		
		Select WaitWindowEvent()
				
			Case #PB_Event_Gadget
				;Popup-Menu anzeigen
				If EventGadget() = 0 And EventType() = #PB_EventType_RightClick
					DisplayPopupMenu(1, WindowID(0))
				EndIf
				
				;Ereignisse im MenuBar auswerten und Requester anzeigen.
			Case #PB_Event_Menu
				
				Select EventMenu()
						
					Case 11 ; About
						MessageRequester("About", "Cool Menu example", 0)
						
					Default
						MessageRequester("Info", "MenuItem: "+Str(EventMenu()), 0)
						
				EndSelect
				
			Case #PB_Event_CloseWindow
				Quit = 1
				
		EndSelect
		
	Until Quit = 1
	
EndIf

End  

Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Re: SetWindowLong_() zerstört Menü-Ereignisse

Beitrag von edel »

Wenn du die Funktion eines Fenster verbiegst, musst du auch die alte Funktion wieder aufrufen und auch die Werte zurueck geben. Es sei denn du moechtest alle Funktionen eines Fensters implementieren.

Code: Alles auswählen

ProcedureReturn CallWindowProc_(*OldProc, hwnd, uMsg, lParam, wParam)
PB_ProcessPureBasicEvents funktioniert nur mit SetWindowCallback, nicht mit SetWindowLongPtr_.
BillTuer
Beiträge: 2
Registriert: 02.02.2015 21:58

Re: SetWindowLong_() zerstört Menü-Ereignisse

Beitrag von BillTuer »

Neeiin :doh: ,

manchmal ist man auch zu blöde, ich habe ProcedureReturn nicht vom Aufruf des CallWindowProc_() geschrieben. :oops:
Manchmal sieht halt den Wald vor lauter Bäumen nicht. Ich dachte ich hätte das davor gesetzt.

Danke dir :allright:
Antworten