SetWindowCallback in einer DLL aufrufen

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
legion
Beiträge: 467
Registriert: 08.10.2006 18:04
Computerausstattung: Intel Core i5-6500 @ 4x 3.6GHz mit Windows 10 Pro, Intel Core-i7 mit Ubuntu 18.04 bionic, x86_64 Linux 4.18.0-16-generic, Microsoft Surface Pro - Windows 10 Pro
Wohnort: Wien
Kontaktdaten:

Beitrag von legion »

Fehler einzugestehen ist eine der grössten Tugenden ! :wink:
Danke !

Lg.Legion
PB 5.71 LTS Windows 10 Pro & Ubuntu 18.04.2 LTS & Linux Mint 19.3
-----------------------------------------------------
Alles ist, wie man glaubt, dass es ist!
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 »

Du kannst SetWindowSubclass() aus PBOSL verwenden, für das Callback in
der DLL, bzw. den Source findeste im Tipps & Tricks Forum (Autor: Edel)
Einfach mal die Beispiele von PBOSL Examples ansehen.
Für die Ereignisse, die die Hauptanwendung benötigt, kannste nachrichten
verschicken mit SendMessage_(hWnd, #WM_USER + 1, 100, 100), oder so
ähnlich.

PS: echte Gadgetereignisse lassen sich auch erzeugen, wenn nötig.
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
legion
Beiträge: 467
Registriert: 08.10.2006 18:04
Computerausstattung: Intel Core i5-6500 @ 4x 3.6GHz mit Windows 10 Pro, Intel Core-i7 mit Ubuntu 18.04 bionic, x86_64 Linux 4.18.0-16-generic, Microsoft Surface Pro - Windows 10 Pro
Wohnort: Wien
Kontaktdaten:

Beitrag von legion »

@ts-soft
He ! Echt super ! Danke ! :D
Den Stoff werde ich mir gleich reinziehen !

@Ligatur
Den CallBack in der Dll mit
ProcedureReturn DefWindowProc_(hwnd,msg,wParam,lParam) hab
ich bis jetzt noch nicht zum Laufen gebracht !
Oder hab ich da wo einen Denkfehler ?

Code: Alles auswählen

Procedure WndProc(hwnd,msg,wParam,lParam)
    *mymsg.MSG = lParam
    myRect.RECT
    GetWindowRect_(*mymsg\hwnd,myRect.RECT)
    Weite = myRect\right - myRect\left    
    Select msg
      Case #WM_MOUSEMOVE
         SelectObject_(TempDC,ImageID(#Image_0))
         StretchBlt_(WinHDC,0,0,Weite,ImageHeight(#Image_0),TempDC,0,0,ImageWidth(#Image_0),ImageHeight(#Image_0),#SRCCOPY)
      Case #WM_ERASEBKGND
         SelectObject_(TempDC,ImageID(#Image_0))
         StretchBlt_(WinHDC,0,0,Weite,ImageHeight(#Image_0),TempDC,0,0,ImageWidth(#Image_0),ImageHeight(#Image_0),#SRCCOPY)
      Case #WM_PAINT
         SelectObject_(TempDC,ImageID(#Image_0))
         StretchBlt_(WinHDC,0,0,Weite,ImageHeight(#Image_0),TempDC,0,0,ImageWidth(#Image_0),ImageHeight(#Image_0),#SRCCOPY)
    EndSelect
  ProcedureReturn DefWindowProc_(hwnd,msg,wParam,lParam)
EndProcedure

ProcedureDLL AddToolBarStretch(WindowHandle) 
 WinHDC  = GetDC_(WindowHandle)
 TempDC  = CreateCompatibleDC_(WinHDC) 
 SelectObject_(TempDC,ImageID(#Image_0))
 StretchBlt_(WinHDC,0,0,Weite,ImageHeight(#Image_0),TempDC,0,0,ImageHeight(#Image_0),ImageWidth(#Image_0),#SRCCOPY)
 SetWindowCallback(@WndProc()) 
EndProcedure
PB 5.71 LTS Windows 10 Pro & Ubuntu 18.04.2 LTS & Linux Mint 19.3
-----------------------------------------------------
Alles ist, wie man glaubt, dass es ist!
Benutzeravatar
Ligatur
Beiträge: 196
Registriert: 09.07.2006 00:41

Beitrag von Ligatur »

Da habe ich wohl nicht genau genug gelesen. SetWindowCallback funktioniert nur, wenn das Fenster innerhalb der DLL erzeugt wird. So must du wie edel schon schrieb SetWindowCallback... mit

Code: Alles auswählen

*OldCallb = SetWindowLong_(WindowHandle, #GWL_WNDPROC, @WndProc())
ersetzen (*OldCallb muss global sein) und im Callback ProcdureReturn DefWindowProc_ ... durch

Code: Alles auswählen

ProcedureReturn CallWindowProc_(*OldCallb, hwnd, msg, wParam, lParam)
ersetzen, dann sollte es funktionieren.
Benutzeravatar
legion
Beiträge: 467
Registriert: 08.10.2006 18:04
Computerausstattung: Intel Core i5-6500 @ 4x 3.6GHz mit Windows 10 Pro, Intel Core-i7 mit Ubuntu 18.04 bionic, x86_64 Linux 4.18.0-16-generic, Microsoft Surface Pro - Windows 10 Pro
Wohnort: Wien
Kontaktdaten:

Beitrag von legion »

@Ligatur
Herzlichen Dank für die Info ! :)
Hab ich gleich mal getestet.
Das Problem dabei ist allerdings, dass durch SetWindowLong_(WindowHandle, #GWL_WNDPROC, @WndProc())
das Fenster eine neu Proceduradresse bekommt. Somit funktioniert auch im
Programm das die DLL aufruft die Ereignisschleife nicht mehr.

Die DLL sollte in jedes PB-Progi eingebunden werden können.
Wer möchte da schon auf sein gutes altes
"Repeat Until Event = #PB_Event_CloseWindow"
verzichten.

Lg. Legion
PB 5.71 LTS Windows 10 Pro & Ubuntu 18.04.2 LTS & Linux Mint 19.3
-----------------------------------------------------
Alles ist, wie man glaubt, dass es ist!
Benutzeravatar
Ligatur
Beiträge: 196
Registriert: 09.07.2006 00:41

Beitrag von Ligatur »

Die PB Ereignisschleife funktioniert so natürlich nicht mehr, aber das dürfte denke ich bei der Lösung von TS Soft auch der Fall sein :? da die angegebene Funktion auf dieser Technik beruhen dürfte (den Namen der Funktion nach zu urteilen.

In deinen Code mit dem Windowhook behandelst du übrigens die Devicecontexte falsch. Was WinHDC betrifft, das wird bei Aufruf der Funktion gesperrt und dann erst irgendwann wieder freigegeben wenn die DLL wieder aus den Speicher entfernt wird. Besser ist es, den Devicekontext vor jeder Befehlsfolge, die einen Devicekontext braucht, zu besorgen und gleich darauf wieder freizugeben, nachdem er nicht mehr gebraucht wird.
Beim TempDC gilt prinzipiell das gleiche, nur kommt hier noch hinzu, das du ihn mit CreateCompatibleDC selber erzeugst, ihn dann aber nur freigiebst, du musst ihn aber löschen mit DeleteDC_(HDC), und das am besten auch gleich nach benutzung, sonst hast du nachher viele Speicherleichen.
Dazu kommt noch, ruft jemand die Funktion AddToolbarStretch mehrfach auf werden jedesmal neue Devicekontexte erzeugt und der Wert der alten geht verloren, diese können dann weder freigegeben werden noch gelöscht.
Benutzeravatar
legion
Beiträge: 467
Registriert: 08.10.2006 18:04
Computerausstattung: Intel Core i5-6500 @ 4x 3.6GHz mit Windows 10 Pro, Intel Core-i7 mit Ubuntu 18.04 bionic, x86_64 Linux 4.18.0-16-generic, Microsoft Surface Pro - Windows 10 Pro
Wohnort: Wien
Kontaktdaten:

Beitrag von legion »

Herzlichen Dank für die genaue Auflistung meiner Fehler! :allright:

Das mit dem Devicecontex und den Speicherleichen wusste ich nicht.
Dachte "freigeben" und die Sache hat sich.
Bin eben nur ein Amateur, der sich immer hohe Ziele steckt. :wink:
Werde die Sache berichtigen.

Die Callbacks in der DLL werd ich mal vergessen.
Der Hook funktioniert und da werd ich weiterarbeiten.

Danke !

Lg. Legion

Berichtigt:

Code: Alles auswählen

Procedure GetMsgProc(code, wParam, lParam)
 *mymsg.MSG = lParam
 myRect.RECT
 GetWindowRect_(*mymsg\hwnd,myRect.RECT)
 Weite = myRect\right - myRect\left
    
   If *mymsg\message = #WM_MOUSEMOVE
     WinHDC  = GetDC_(WindowHandle) : TempDC  = CreateCompatibleDC_(WinHDC)
     SelectObject_(TempDC,ImageID(#Image_0))
     StretchBlt_(WinHDC,0,0,Weite,ImageHeight(#Image_0),TempDC,0,0,ImageWidth(#Image_0),ImageHeight(#Image_0),#SRCCOPY)
     DeleteDC_(WinHDC) : DeleteDC_(TempDC)
   
   ElseIf *mymsg\message = #WM_ERASEBKGND
     WinHDC  = GetDC_(WindowHandle) : TempDC  = CreateCompatibleDC_(WinHDC)
     SelectObject_(TempDC,ImageID(#Image_0))
     StretchBlt_(WinHDC,0,0,Weite,ImageHeight(#Image_0),TempDC,0,0,ImageWidth(#Image_0),ImageHeight(#Image_0),#SRCCOPY)
     DeleteDC_(WinHDC) : DeleteDC_(TempDC)
   
   ElseIf *mymsg\message = #WM_PAINT
     WinHDC  = GetDC_(WindowHandle) : TempDC  = CreateCompatibleDC_(WinHDC)
     SelectObject_(TempDC,ImageID(#Image_0))
     StretchBlt_(WinHDC,0,0,Weite,ImageHeight(#Image_0),TempDC,0,0,ImageWidth(#Image_0),ImageHeight(#Image_0),#SRCCOPY)
     DeleteDC_(WinHDC) : DeleteDC_(TempDC)
   EndIf
  
  ProcedureReturn CallNextHookEx_(@GetMsgProc(), code, wParam, lParam)
EndProcedure

ProcedureDLL AddToolBarStretch(WHandle) 
 WindowHandle = WHandle
 WinHDC  = GetDC_(WindowHandle)
 TempDC  = CreateCompatibleDC_(WinHDC) 
 SelectObject_(TempDC,ImageID(#Image_0))
 StretchBlt_(WinHDC,0,0,Weite,ImageHeight(#Image_0),TempDC,0,0,ImageHeight(#Image_0),ImageWidth(#Image_0),#SRCCOPY)
 SetWindowsHookEx_(#WH_GETMESSAGE	,@GetMsgProc(),0,GetWindowThreadProcessId_(WindowHandle,#False))
 DeleteDC_(WinHDC)
 DeleteDC_(TempDC)  
EndProcedure

ProcedureDLL DetachProcess(Instance)
  UnhookWindowsHookEx_(@GetMsgProc())
EndProcedure 
PB 5.71 LTS Windows 10 Pro & Ubuntu 18.04.2 LTS & Linux Mint 19.3
-----------------------------------------------------
Alles ist, wie man glaubt, dass es ist!
Benutzeravatar
Ligatur
Beiträge: 196
Registriert: 09.07.2006 00:41

Beitrag von Ligatur »

Das ist so noch nicht ganz richtig, DeleteDC darf man nur auf mit Create...DC selbsterstellte Devicekontexte anwenden nicht aber auf mit GetDC erhaltene, bei diesen war das ReleaseDC schon richtig.
Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Beitrag von edel »

Wenn man ein Callback mit SetWindowLong oder SetWindowSubclass erstellt,
laeuft alles so weiter wie bisher, nur das man eben noch die Moeglichkeit hat,
die Events selbst zu verarbeiten.

So sieht der Funktionsaufruf in pb aus :

Code: Alles auswählen

 PB Callback -> System Callback
Schaltet man nun sein eigenen dazu :

Code: Alles auswählen

 Eigener Callback -> PB Callback -> System Callback
Vorausetzung fuer den eigenen Callback ist natuerlich das man die Nachricht
auch an den alten Calback weiterleitet (callwndproc oder defsubclassproc).
Muss man zwar nicht, aber dann darf man sich nicht wundern wenn die PB
schleife nicht mehr funktioniert.
Benutzeravatar
legion
Beiträge: 467
Registriert: 08.10.2006 18:04
Computerausstattung: Intel Core i5-6500 @ 4x 3.6GHz mit Windows 10 Pro, Intel Core-i7 mit Ubuntu 18.04 bionic, x86_64 Linux 4.18.0-16-generic, Microsoft Surface Pro - Windows 10 Pro
Wohnort: Wien
Kontaktdaten:

Beitrag von legion »

@Ligatur
Das mit dem DeviceContext hab ich jetzt verstanden !
Danke !

@edel
Erstmal danke für deine Hilfe !
Wie man die Nachricht neuerlich an den alten Callback weiterleitet durchblicke ich leider nicht. Ich verstehe zwar was du meinst, kann es aber nicht realisieren. Über "DefSubclassproc und SetWindowSubclass konnt ich in der W32API-Referenz nichts finden. Und mit SetWindowLong bin ich bis jetzt
gescheitert.

:) Vielleicht könntest du mir das anhand eines kleinen Beispiels erklären.
Danke !

Lg. Legion
PB 5.71 LTS Windows 10 Pro & Ubuntu 18.04.2 LTS & Linux Mint 19.3
-----------------------------------------------------
Alles ist, wie man glaubt, dass es ist!
Antworten