Le contrôle 'xxx' a pas de fenêtre parent
Je suis a été d'essayer d'écrire une bibliothèque dll en Delphi avec une fonction qui crée une instance d'un TFrame descendant et le renvoie. Mais quand j'ai importé cette fonction dans une application, à chaque fois que je l'ai appelé, je voudrais obtenir une exception, comme "le 'xxx' contrôle a pas de fenêtre parent". Je ne suis pas sûr à 100%, mais l'exception est apparu dans le constructeur de cette classe lorsque l'un des contrôles d'interface utilisateur graphique a été consulté.
Pourriez-vous svp me dire quelle est la raison de ce comportement est? Devrais-je utiliser TForm descendants au lieu de cela ou est-il une meilleure solution?
Merci!
OriginalL'auteur Mariusz Schimke | 2010-09-23
Vous devez vous connecter pour publier un commentaire.
Sur l'erreur
Que le message d'erreur est généré à partir de l'Contrôles.pas d'unité, à partir de la
TWinControl.CreateWnd
méthode. Essentiellement que le code est utilisé pour créer la poignée de la Fenêtre pour votre twincontrol a descendant (TFrame, TButton, TEdit... s'il peut avoir le focus du clavier c'est un twincontrol a descendant), et c'est effectivement une très sage, un message d'erreur: Vous ne pouvez pas avoir une Fenêtre sans WindowParent, et puisque nous parlons de la VCL ici, il fait beaucoup de sens pour essayer et obtenir le handle de fenêtre parent de twincontrol a.Parent; Et ce n'est pas affectée.Ce n'est pas POURQUOI le message d'erreur popping up. Vous obtenez de voir ce message d'erreur parce que le code que vous utilisez pour configurer l'image d'un handle de Fenêtre pour une certaine opération. Il pourrait être n'importe quoi, comme le réglage de la Légende de certains composants (en interne implique un handle de fenêtre certaine calcul). Personnellement, je déteste vraiment quand cela arrive. Quand je crée des interfaces de code, j'ai essayer de retarder l'attribution des Parents autant que possible, dans une tentative de retarder la création de la fenêtre, donc je suis mordu par de nombreuses reprises.
Spécifiques à votre fichier DLL utilisation, correction possible
Je vais mettre mon psycho lecteur d'esprit chapeau. Puisque vous avez besoin de renvoyer une IMAGE à partir de votre fichier DLL, et vous ne pouvez pas retourner le Cadre réel parce que c'est un Delphi-objet spécifique et vous n'êtes pas autorisé à retourner en Delphi objets spécifiques sur des limites de la DLL, je suppose que vous êtes de retour d'une Poignée de Fenêtre, comme toutes les belles de l'API de faire, à l'aide d'une définition de fonction comme ceci:
Le problème, c'est que la routine nécessite la création effective de la Poignée de la Fenêtre, par un appel à
TWinControl.CreateWnd
, et, à son tour, appel nécessite un parent handle de fenêtre pour configurer l'appel àWindows.CreateWindowEx
, et la routine ne pouvez pas obtenir un handle de fenêtre parent, de sorte qu'il erreurs.Essayez de remplacer votre fonction avec quelque chose au jeu complet des lignes de:
... c'est à dire: utiliser le
CreateParented(AParentWindow:HWND)
constructeur, pas l'habitudeCreate(AOwner:TComponent)
et de passer un propriétaire HWND votre DLL.Ce n'est pas OK pour les versions raisons: l'Utilisation de l'objet retourné nécessite la connaissance de la disposition de la mémoire, et qui est sujet à changer (il peut changer avec Delphi version). Il fonctionne lorsque vous le tester, et cela ne fonctionne pas si le fichier Exe et Dll sont construits avec le même compilateur et même les paramètres du compilateur, mais si vous allez à imposer de telles restrictions, vous pouvez aussi bien utiliser des packages.
Merci, c'est goot pour le savoir. J'ai fait ce que vous avez proposé et je suis encore en train de l'exception :-(. La fonction exportée fait ceci: Result := TFrame1.CreateParented(ParentWindowHandle); Et ParentWindowHandle est un handle de la fenêtre principale d'une application qui appelle la méthode (de Soi.Poignée, lorsqu'il est appelé à partir de la fenêtre principale de la classe).
Debug plus loin. Avec votre DLL dans l'éditeur, cliquez sur Exécuter -> Processus de Chargement et de chargement de l'exécutable qui utilise votre DLL. Faire tout ce que vous avez besoin avec l'EXE pour le charger votre fichier DLL et appelez votre fonction. L'IDE s'arrêter sur l'erreur, regardez la pile d'appel, trouver le code fautif et assurez-vous que le Parent est attribué.
La bonne façon de déboguer le fichier DLL pour spécifier l'Hôte de l'Application (exe) dans les Options de Projet, puis de le faire EXÉCUTER. L'Application Hôte démarre et lorsque l'erreur se produit, vous seriez capable de debug comme vous le feriez normalement.
OriginalL'auteur Cosmin Prund
Il ya quelques choses importantes à retenir:
Essayer de reproduire votre problème à l'intérieur de l'EXE; si vous ne pouvez pas reproduire, c'est probablement la première chose dans la liste ci-dessus.
--jeroen
OriginalL'auteur Jeroen Wiert Pluimers
Sonne comme vous avez simplement besoin d'affecter le composant (une forme ou d'une partie d'un formulaire, comme un panneau) qui détient le cadre de theframe.parent.
Vous ne pouvez pas faire de la GUI de travail dont il est affecté. Les cadres sont des pièces de formes pour la réutilisation, et normalement besoin d'assigner une mère pour eux.
Déplacer le code de la GUI pour onshow ou d'une procédure d'appel explicitement, de sorte que le code appelant peut affecter parent.
Ou faire le parent d'un paramètre de la fonction.
fixe. Écrit dans la hâte est toujours un problème pour moi. Travail sur toutes les peines à la fois 🙂
OriginalL'auteur Marco van de Voort
J'ai trouvé ceci (CreateParams est appelée dans le cadre de CreateWnd):
Et De L'Application.Handle = 0 donc il jette toujours l'erreur plus tard dans CreateWnd.
Après la lecture de ce
Delphi: Comment appeler hérité hérité de l'ancêtre sur une méthode virtuelle?
J'ai résolu en remplaçant CreateParams dans mon cadre de manquer le tCustomFrame version:
Maintenant, il suffit de jeter des erreurs lorsque vous essayez de définir le focus sur subcontrols, je pense que je vais le corriger en cas d'interception d'WM_FOCUS mais nous allons comment il va partir d'ici.
OriginalL'auteur Frank
Vous pouvez éviter ce message par l'affectation de néant pour le parent événement OnClose, parfois cela fonctionne:
Kachwahed: Vous ne devez pas programme par la conjecture. Il sera juste de la portée de votre code inutiles ordures qui, habituellement, agit comme un catalyseur de subtiles et des bugs. Oui, il peut être difficile, mais vous devez faire l'effort de l'analyse des causes profondes de sorte que vous pouvez bien comprendre le problème. Dans ce cas particulier, votre réponse est totalement hors de propos à l'OP du problème.
Et dans un deuxième point, vous ne devriez pas être en train d'essayer "d'éviter les messages d'erreur". Les messages d'erreur ne sont pas un problème ... Ils sont tout simplement un tir à propos d'un problème. Donc, ne pas tirer sur le messager. Comprendre ce que le problème, et fix réel problème!
OriginalL'auteur Kachwahed
Je pense que c'est très cool de la solution. Je pense qu'il n'est pas essayé avant 🙂
Je suis à l'aide d'un Mannequin Parent (qui est une Forme).
OriginalL'auteur suat dmk