2010-11-17 24 views
2

J'ai une application Vb.net faite par une tierce partie, que j'ai besoin de contrôler en utilisant des ressources externes à partir d'un environnement simulé et qui ne doit pas interagir avec le bureau. Pour simuler les entrées qu'un utilisateur devrait normalement saisir à partir d'un écran spécial avec des touches spécifiques autour de lui, j'ai construit une bibliothèque de contrôle de test pour le contrôler et envoyer l'image de formulaire à un .bmp. Le formulaire ne peut pas être visible et affiché dans la barre des tâches, la sortie bmp sera affichée par l'environnement simulé. L'utilisation de PostMessage et sendKeys fonctionne bien tant que je n'ai pas ShowInTaskbar = False pour le formulaire principal. Après avoir lu beaucoup de tests, j'ai appris assez pour essayer ce qui semble être la seule chose qui fonctionnerait. J'ai créé un formulaire que j'ai paramétré en utilisant le paramètre HWND_MESSAGE, cela devrait créer un Message-Only Windows, qui est supposé recevoir postMessage, et sous-classer ses événements. msdn.La fenêtre Message-Only ne reçoit pas PostMessage

StackOverflow already about this

Malheureusement, je ne peux pas sembler le faire fonctionner, et j'espérais que quelqu'un pourrait me dire ce que je fais wrong.I ont été testé plusieurs façons différentes trouvés à travers le web à propos de .net, et à court d'aller dans le fil de discussion peek et feed (peut-être (peut-être) mon dernier espoir), ils semblent tous fonctionner jusqu'à ce que je sors les formulaires de la barre des tâches.

Ok, voici le code:

Le MsgOnly.vb

Public Class MsgHandling 

DllImport("user32.dll", SetLastError:=True,CharSet:=CharSet.Auto)> _ Public Shared Function SetParent(ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As IntPtr End Function

Private Shared HWND_MESSAGE As IntPtr = New IntPtr(-3)

Public Event CallBackProc(ByRef m As Message) 

Public Sub setParent() 
    SetParent(Me.Handle, HWND_MESSAGE) 
End Sub 
Protected Overrides Sub WndProc(ByRef m As Message) 

    RaiseEvent CallBackProc(m) 'then RaiseEvent 
    MyBase.WndProc(m) 
End Sub 

End Class 

partie subclassing sous la forme (ne peut pas montrer plus que ce que gère la sous classage, J'espère que cela suffira)

Public WithEvents Msg As New MsgHandling 

Private Sub XXXXX_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 

    '----snips 

    Msg.setParent() 

    '----snips 
end sub 


Private Sub CallBackProc(ByRef m As System.Windows.Forms.Message) Handles Msg.CallBackProc 

Me.Text = "Rx events " & m.LParam.ToString() & " " & m.WParam.ToString() 

WndProc(m) 

End Sub 

forme de test

Public Class Form1 

<DllImport("user32.dll")> _ 
Private Shared Function SetForegroundWindow(ByVal hWnd As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean 
End Function 

Private Shared Function FindWindow(_ 
    ByVal lpClassName As String, _ 
    ByVal lpWindowName As String) As IntPtr 
End Function 
Public Shared Function SetWindowPos(_ 
ByVal hWnd As IntPtr, _ 
ByVal hWndInsertAfter As IntPtr, _ 
ByVal X As Int32, _ 
ByVal Y As Int32, _ 
ByVal cy As Int32, _ 
ByVal uFlags As Int32) _ 
As Boolean 
End Function 
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long 
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long 
Private Declare Function AllowSetForegroundWindow Lib "user32" Alias "AllowSetForegroundWindow" (ByVal dwProcessId As Integer) As Boolean 
Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As String) As Integer 

Public myProcess As Process = New Process() 
Private Const WM_KEYDOWN As Long = 100 
Private Const WM_RBUTTONDOWN As Long = 204 
Public Shared HWND_MESSAGE As IntPtr = New IntPtr(-3) 




Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 
    myProcess.StartInfo.FileName = "...\XXXXXX.exe" 'Not real name 
    myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Normal 
    myProcess.EnableRaisingEvents = True 
    AddHandler myProcess.Exited, AddressOf Me.SendKeysTestExited 
    myProcess.Start() 

End Sub 
Friend Sub SendKeysTestExited(ByVal sender As Object, _ 
     ByVal e As System.EventArgs) 
    Dim myRxProcess As Process = DirectCast(sender, Process) 

     myRxProcess.Close() 

End Sub 

Private Sub Form1_KeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown 

    Dim tHwnd As Long 
    Dim rslt As Boolean 

    If myProcess.Responding Then  

     tHwnd = FindWindowEx(HWND_MESSAGE, 0, 0, 0) 
     PostMessage(HWND_MESSAGE, WM_RBUTTONDOWN, 0, "TEXT TO SEND") 

    Else 
     myProcess.Kill() 
    End If 
End Sub 


Private Sub Form1_FormClosed(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles MyBase.FormClosed 
    myProcess.Close() 
End Sub 
End Class 

Pas vraiment sûr de ce que d'autres détails que je peux fournir pour l'instant. Quelqu'un comme une idée ou des moyens que je n'ai pas trouvé?

Merci pour toute contribution

+1

Il est assez extraordinaire de voir à quelle fréquence les programmeurs doivent faire face à de telles difficultés pour maintenir les logiciels hérités qui ne sont plus supportés par leur fournisseur d'origine. Pour une raison quelconque, généralement mauvaises. Hmm, idée d'entreprise: je parie que quiconque a écrit que le code d'abord est toujours là. Probablement dans un travail différent avec une femme divorcée et 2 1/2 enfants qui sont sur le point d'entrer au collège. Ne serait-ce pas génial s'il vous appelait et vous demandait ce qu'il pouvait faire pour aider? Pourrais-je le mien, pour tout ce que je sais. –

+0

En fait, ce n'est pas exactement un logiciel hérité, mais plutôt une application fonctionnant dans un environnement normal recevant des clés affectées à des touches spéciales autour de l'écran (paramètres avioniques) et l'utilisant dans un environnement simulé. . Le Dev original ne pourra malheureusement pas aider, car nous essayons d'utiliser leur logiciel (avec tous les droits pour le faire) d'une manière qui n'était pas prévue. Nous avons aussi besoin d'un changement minimal pour ne pas vraiment ramifier et utiliser le même code dans les deux paramètres, en l'adaptant en fonction de l'environnement. – Shuryno

+1

+1 pour la question, +1 pour l'avatar! Allez Nordiques! – Goldorak84

Répondre

2

J'ai trouvé un problème. Il semble que le problème vient du fait que le handle de Windows n'est pas trouvé avec les fonctions de recherche. J'ai essayé plusieurs façons, mais puisque les messages seulement ne sont pas énumérés, je ne peux pas boucler, ou du moins je n'ai pas réussi.

Donc, je crée un fichier avec le handle, que le programme externe lit et l'utilisation qui gère pour faire le PostMessage. Cela fonctionne bien pour le moment. J'aimerais pouvoir trouver un meilleur moyen, mais au moins, j'ai quelque chose à proposer comme solution.

Je suis toujours ouvert à la suggestion ou à une autre solution de contournement possible :).

+0

Donc, pour ceux qui cherchent le même genre de solution, ce que j'ai fait, c'est créer un sharedMemory où j'ai écrit le handle que le programme natif lit. Là, j'ai également marshalé le tableau d'octets de sortie bitmap du formulaire dans le mappage de fichiers. Je suis toujours à se demander pourquoi je ne peux pas créer un DIB sans charger un fichier à partir du disque sur la création bitmap, un bitmap créé tout autre est DDB.Il semble que marshaling un tableau dynamique dans une structure n'est pas supporté (Il faut) – Shuryno