2017-10-17 47 views
1

J'ai besoin de pomper des messages COM en attendant qu'un événement répare un blocage. Il est préférable de pomper le moins possible de messages juste pour traiter cet appel COM. Le meilleur candidat pour ce rôle est CoWaitForMultipleHandles mais starting from Vista il pompe WM_PAINT en plus des messages COM. Le pompage de WM_PAINT est trop dangereux pour moi du point de vue de la rentrée et je ne veux pas installer une base de données de shim personnalisée comme solution à ce problème. J'essaie de pomper manuellement les messages COM envoyés à la fenêtre des messages masqués uniquement.Comment pompe messages COM dans STA sans pompage WM_PAINT?

J'ai trouvé deux façons d'obtenir HWND de la fenêtre cachée:

  1. ((SOleTlsData *) NtCurrentTeb()->ReservedForOle)->hwndSTA à l'aide de .NET ntinfo.h de base. Cela semble être une solution non documentée et pas fiable en termes de changements futurs.
  2. Trouver la fenêtre de OleMainThreadWndClass comme suggéré dans this question. Le problème est que CoInitialize ne crée pas la fenêtre. Il est créé plus tard lors du premier appel inter-appartement qui peut ou peut ne pas arriver dans ma demande. Exécuter la boucle de recherche chaque fois que j'ai besoin de HWND est mauvais du point de vue des performances, mais la mise en cache de HWND semble impossible parce que je ne sais pas quand il est créé.

Existe-t-il un moyen de déterminer si la fenêtre masquée est créée pour l'appartement actuel? Je suppose que ce sera moins cher que la boucle et puis je pourrais trouver et cache HWND.

Existe-t-il un meilleur moyen de pomper des messages COM sans pomper WM_PAINT?

Mise à jour: Vous pouvez forcer la création de la fenêtre en appelant CoMarshalInterThreadInterfaceInStream pour n'importe quelle interface. Puis appelez Co­Release­Marshal­Data pour libérer le pointeur de flux. C'est ce que je finis par faire avec la recherche de OleMainThreadWndClass.

+1

Si vous voulez opter pour des routes sombres, vous devriez pouvoir taper AppCompatFlags directement dans la mémoire PEB: https://social.msdn.microsoft.com/Forums/sqlserver/en-US/5a28a9f5-5711-4efa -843e-e98927fa2b92/dcom-dans-vista-spécifiquement-traitement-wmpaint-messages? Forum = windowsgeneraldevelopmentissues. Je pense que vous pouvez désactiver la pompe WM_PAINT si binaire-et actuel AppCompatFlags avec la valeur de l'indicateur 0x100000. Remarque Le décalage d'AppCompatFlags par rapport au début du PEB est différent de x64 et x32. –

+0

Je ne peux pas penser à une seule bonne raison de ne pas traiter les messages WM_PAINT. Si quelque chose est "dangereux" dans votre gestionnaire WM_PAINT, je suppose que vous faites quelque chose dans WM_PAINT que vous ne devriez pas faire. Le gestionnaire WM_PAINT doit uniquement lire l'état (toutes les variables nécessaires pour déterminer ce qu'il doit dessiner) et non modifier l'état. –

+0

@MichaelGunter, les grilles virtuelles font beaucoup de choses intéressantes dans les gestionnaires WM_PAINT. –

Répondre

-3

WM_PAINT est généré lorsqu'il n'y a aucun autre message dans la file d'attente de messages et que vous exécutez GetMessage ou utilisez PeekMessage.

Mais WM_PAINT n'est envoyé que si vous l'envoyez. De plus, il n'y a pas de nouveau message WM_PAINT jusqu'à ce qu'une fenêtre soit à nouveau invalidée.

Donc cela dépend de vous si vous envoyez un message WM_PAINT ou non. Mais soyez conscient, il y a d'autres chances de réentrées comme un message WM_TIMER.

Les détails à ce sujet sont dans les documents pour WM_PAINT. De mon point de vue, la meilleure solution serait de vous mettre en mode "wait", qui peut même gérer WM_PAINT dans cet état d'attente indéfini. Vous savez quand vous êtes rentré. C'est toujours après un message WM_PAINT ... ou des messages similaires qui arrivent comme les autres messages d'entrée. Donc je ne vois aucun problème ici. Une STA a un thread et vous traitez toujours les messages jusqu'à la fin, jusqu'à ce que vous exécutiez GetMessage, lanciez une boîte de dialogue modale ou affichez un MessageBox. Lorsque vous êtes à l'intérieur d'un message, rien ne vous dérange.

Peut-être une autre solution serait d'attendre dans un deuxième thread pour cet événement. Ce thread peut ne pas avoir de fenêtres et vous pouvez traduire l'événement en tout ce dont vous avez besoin dans votre application.

Donc, votre question peut ne pas avoir assez d'informations sur la façon dont cette impasse apparaît vraiment. Donc, cette réponse peut ne pas être suffisante. Après avoir écrit ceci, j'ai tendance à penser qu'il s'agit d'un problème XY.