Impossible de focaliser une fenêtre désactivée ou invisible

Résolu
Guillemouze Messages postés 991 Date d'inscription samedi 25 octobre 2003 Statut Membre Dernière intervention 29 août 2013 - 15 nov. 2006 à 12:10
 fredelem - 5 mars 2009 à 21:15
bien le bonjour, me revoila pour une question un peu bete mais je ne trouve pas de solution.
j'ai une form qui contient plusieurs panels, qu'on peut assimiler a des tabsheet (onglets). j'ai un composant que je deplace (via la propriete parent) sur le panel visible, pour un sous ensemble de mes panels.
plus clairement, j'ai 5 panels, et si le panel visible est le numero 1, 2 ou 4, alors je deplace mon composant dessus, sinon, je le laisse sur le dernier panel qu'il a eu.

Ensuite, sur ma form, j'ai un keyPreview qui donne le focus au composant.
le probleme, c'est que si le panel visible ne contient pas le composant (panel 0 ou 3 ds mon exemple), alors j'ai le joli message:
Le projet Machin.exe a provoqué une classe d'exception EInvalidOperation avec le message 'Impossible de focaliser une fenêtre désactivée ou invisible'.  Processus stoppé. Utilisez Pas-à-pas ou Exécuter pour continuer.

j'ai essaye de faire
if (monComposant.visible) then
    monComposant.focused := true;
mais la propriete visible est true quand il est sur un panel masqué.

PS: mes panels sont placés sur des KWizardPage, et l'arborescence de ces panels n'est pas la meme en fonction du panel.

est ce que quelqun aurait une solution?

26 réponses

Guillemouze Messages postés 991 Date d'inscription samedi 25 octobre 2003 Statut Membre Dernière intervention 29 août 2013 6
15 nov. 2006 à 14:27
pour ceux que ca interesse, j'ai fait une fonction qui permet de savoir si un control peut recevoir le focus. La voici :

function Focusable(ctrl: TControl): boolean;
begin
  if ctrl.Visible then
  begin
    if ctrl.Parent = nil then
      Result := true
    else
      Result := Focusable(ctrl.Parent);
  end
  else
    Result := false;
end;
3
japee Messages postés 1727 Date d'inscription vendredi 27 décembre 2002 Statut Modérateur Dernière intervention 6 novembre 2021 8
15 nov. 2006 à 14:51
Salut,

Il y a aussi TWinControl.CanFocus dans Control.pas.

Bonne prog'
3
cs_Loda Messages postés 814 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 30 juillet 2009 3
15 nov. 2006 à 13:46
salut,

et avec
if (monComposant.Parent.visible) then
monComposant.focused := true;

?

bon code,
0
Guillemouze Messages postés 991 Date d'inscription samedi 25 octobre 2003 Statut Membre Dernière intervention 29 août 2013 6
15 nov. 2006 à 14:01
bah en fait, comme je l'ai dit pas du tout clairement dans le PS, l'arborescence est differente.
je peux avoir

root
+-panelX
    +-panel1
+-panelX
    +-panelY
       +-panel2

donc je ne sais pas quel parent n'est pas visible

par contre je peu peut etre faire une boucle du genre
Result := true;
x := MonComposant;
while (result) and (x <> root) do
begin
    if not x.visible then result := false;
    x := x.parent
end;
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Guillemouze Messages postés 991 Date d'inscription samedi 25 octobre 2003 Statut Membre Dernière intervention 29 août 2013 6
15 nov. 2006 à 14:04
merde ca rend pas bien du tout a cause de l'image.
je recopie l'arborescence:

root
+-panelX
    +-panel1
+-panelX
    +-panelY
       +-panel2
0
Guillemouze Messages postés 991 Date d'inscription samedi 25 octobre 2003 Statut Membre Dernière intervention 29 août 2013 6
15 nov. 2006 à 16:02
merci japee
0
japee Messages postés 1727 Date d'inscription vendredi 27 décembre 2002 Statut Modérateur Dernière intervention 6 novembre 2021 8
15 nov. 2006 à 23:33
Salut,

Tu as des questions fondamentalement intéressantes,
Guillemouze.
Ca
m'a inspiré cette ch'tite fonction que je trouve plutôt sympa, voire utile,
lol :

function
ObjetcCanFocus(Obj: TObject): Boolean;
begin
  Result := Obj is
TWinControl and TWinControl(Obj).CanFocus;
end;

Bonne prog'

japee
0
cs_Loda Messages postés 814 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 30 juillet 2009 3
16 nov. 2006 à 12:57
@japee:

c'est pas pour pinailler, mais tu ne test pas assigned et si tu compiles ce code en évaluation booléen complète, t'aura une exception de transtypage ...

mais je garde l'idée dans un coin... :)

Result := assigned(obj);
if Result then result := obj is TWinControl;
if result then result := TWinControl(Obj).CanFocus;

A+
0
japee Messages postés 1727 Date d'inscription vendredi 27 décembre 2002 Statut Modérateur Dernière intervention 6 novembre 2021 8
16 nov. 2006 à 14:39
Salut Loda,

D'accord avec toi sur l'évaluation booléenne complète, d'ailleurs voir débat sur le sujet dans mon source TPulseButton.
Donc, au développeur de vérifier la directive, ou d'adapter ce code, selon sa préférence.

Pour le reste, je suis plus perplexe : si je "Free" et "Nil" proprement l'Object, je n'ai pas besoin de tester "if Assigned", le résultat retourné sera False, puisque la condition "Obj is TWinControl" n'est par remplie...
C'est un peu étonnant, mais ça fonctionne, sauf preuve du contraire.

Bonne prog'

japee
0
cs_Loda Messages postés 814 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 30 juillet 2009 3
16 nov. 2006 à 16:06
en fait, j'ai dit une bêtise, "is" fonctionne correctement avec un ptr à nil. alors le assigned est de toute façon inutile. T'as bien raison.

Par contre, je te rappel que le assigned ne test pas si le ptr est toujours valide, mais bien si il vaut nil. Tant que tu affect nil a tes ptr, c'est bon :)

Mais je ne crois pas que la lib fasse des freeAndNil pour les compo des forms.... enfin, j'ai rien vu dans TComponent.DestroyComponents; il les vire de la list, mais pas d'affectation.
De toute façon, tu ne peut pas garantir que tu ne reçoive pas un "vieux" pointeur non mit à nil .... et comme t'as aucun moyen de le tester...(a part un try except)

quand à $BoolEval, bin on avait déjà parlé.... si tu sais ce que tu fais, pas de blem. sinon des fois, bonjour pour trouver l'erreur ...

bon, bon,

A+
Loda
0
Guillemouze Messages postés 991 Date d'inscription samedi 25 octobre 2003 Statut Membre Dernière intervention 29 août 2013 6
16 nov. 2006 à 16:34
c'est clair, je trouve que c'est une connerie l'evaluation booleenne complete !!!!
j'aimerai bien savoir quelles sont les motivations des gens qui l'utilisent.
perso je trouve que :
if (unTruc) and (MaListe.extract(unPtr) = unPtr)  then
ou un truc dans le genre, je trouve pas ca propre du tout. Si on veut faire la deuxieme evaluation quelle que soit la valeur de UnTruc, et ben on le fait avant et c'est tout :/
0
cs_Loda Messages postés 814 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 30 juillet 2009 3
17 nov. 2006 à 11:01
ça dépend de ce que tu veux faire.

Note que dans les langages dit fiable (ADA, ...) le compilateur est toujours en évaluation bool complet. Dans d'autre comme le C, ce n'est pas le cas.


Exemple "pro" eval Boo complète:

if ChargeMainForm and
ChargeDockForm and
ChargeOption then begin
MontrerElements;
end;

et de manière général, tout les bool calculé à partir de valeur de retour de fonction modifiante.

Exemple "contre" l'Eval Bool complète:
(ou comment coder en delphi comme si c'était du c)

if PeutOuvrir and OpenDialog.Execute then
Traiter(OpenDialog.FileName);

if (index <> -1) and (MonTab[index] > Limit) then begin
end;

et tout les gros test avec plein de bool et de calcul (non modifiant) sur des valeurs réel.

voilà.

faut juste faire gaffe a ce qu'on fait. et mon avis perso: je me détache le plus possible des options de compilateur et des version de compilateur lorsque je fait des lib ou du code avec une long durée de vie. Et je choisit une config adapté pour les petits projets.

Note que faite des fonction modifiante n'est pas une bonne habitude de programmation, mais c'est très pratique....

je m'étale un peu là...

aller A+

bon code,
0
Guillemouze Messages postés 991 Date d'inscription samedi 25 octobre 2003 Statut Membre Dernière intervention 29 août 2013 6
17 nov. 2006 à 11:17
heu qu'entend tu par "fonction modifiante"?
ca par exemple :
function modif(l: TList): Boolean;
begin
    l.clear;
    retrurn true;
end;

?

en tout cas, c'est vrai que c'est tres dangereux de faire du code qui depend du compilateur.
desormais je vais essayer de coder independament de la valeur de l'eval bool complete, mais je trouve ca beaucou moins clair.
par exemple

if (assigned(l)) and (i < l.count) and (l[i] <> nil) then
begin
    ...
end;

est bcp plus lisible (a mon gout) que

if (assigned(l)) then
begin
     if (i < l.count) then
    begin
         if (l[i] <> nil) then
        begin
            ...
        end;
    end;
end;
0
cs_Loda Messages postés 814 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 30 juillet 2009 3
17 nov. 2006 à 14:23
bin remplace par

if assigned(l) then if i < l.count then if l[i] <> nil then begin

end;

ou test assigned(l) avant avec
function MyFct(l:tlist) : TObject;
begin
result := nil;
if not assigned(l) then exit;
//rest du code ou l est ok.
end;

bon bon, je crois qu'on peut arrêter la le HS. non? sinon, on peut ouvrir un autre post sur les directive de compilation :)

bon code,
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
17 nov. 2006 à 15:23
Salut,
l'évaluation
booleenne complète ne dépend pas de la manière dont le code à été écrit:

Ceci:




if (assigned(l)) and (i < l.count) and (l[i] <> nil) then ...








et ceci:




if assigned(l) then if i < l.count then if l[i] <> nil then ...




sera évalué de la même manière si {$B-} est déclaré




Extait de l'aide de Delphi:






La directive $B permet d'alterner entre les deux modèles de génération de code pour les opérateurs booléens and et or.
En mode {$B+}, le compilateur génère un code évaluant entièrement les expressions booléennes. Tous les opérandes des expressions booléennes contenant des opérateurs and et or sont alors évalués, même si le résultat de l'expression totale est déjà connu.
En mode {$B-}, le compilateur génère un code d'évaluation "court-circuit" des expressions booléennes. Cela signifie que l'évaluation s'arrête à partir du moment où le résultat de l'expression devient évident dans l'ordre d'évaluation de gauche à droite.

Pour plus d'informations, recherchez "opérateurs booléens" dans l'index de l'aide du langage Pascal Objet.




 






@+
Cirec





0
Guillemouze Messages postés 991 Date d'inscription samedi 25 octobre 2003 Statut Membre Dernière intervention 29 août 2013 6
17 nov. 2006 à 15:41
@Cirec

c'est ce qu'on dit ! si on est en mode {$B-}, ces 2 instructions sont equivalentes. par contre, en mode {$B+} (evaluation booleenne complete), alors il risque fortement d'y avoir des plantages pour la premiere instruction
(if (assigned(l)) and (i < l.count) and (l[i] <> nil) then)

 
@Loda
désolé, les exit et autres break sont contre ma religion
0
cs_Loda Messages postés 814 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 30 juillet 2009 3
17 nov. 2006 à 16:45
CanFocus:

juste en passant rapidement, j'ai fait un code genre:

if Xxx.CanFocus then Xxx.SetFocus;
et deviennez.... à l'exécution le beau message "ne peut pas focuser une fenêtre desactivée ou invisible"... j'aime....

@Guillemouze:
on vit dans des pays libre. Chaqu'un choisit sa religion :D
perso, je trouve qu'un petit if exit en début de function est mieux qu'un if begin-end de 80 lignes. sans parler de l'indentation. mais bon. c'est un débat sans fondement et sans but. c'est juste un question de préférence perso.
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
17 nov. 2006 à 17:23
"désolé, les exit et autres break sont contre ma religion"

je trouve personnellement que c'est dommage de s'en passer. Si déjà le language nous les mets à disposition.

En plus Exit et Break sont des fonctions très "propres"

un petit exemple pour comprendre :

      Try
        {On alloue suffisement de mémoire}
        GetMem(Buffer, 255);
        {On ouvre le presse-papier}
        OpenClipBoard(0);
        {On récupère le Handle des données}
        Data := GetClipboardData(CF_TEXT);
        If Data = 0 then Exit else   //----- En exécutant Exit ici, la boucle saute directement à Finally
        begin
          {On copie les données 255 caractères Max}
          StrLCopy(Buffer, GlobalLock(Data), 255);
          GlobalUnlock(Data);
        end;
      Finally  // -----  ici afin de libérer les objets et la mémoire et ensuite elle quitte la méthode
        {On ferme le presse-papier}
        CloseClipBoard;
        {On libère la mémoire}
        ClpBrd : = String(Buffer);
        FreeMem(Buffer);
      End ;

Comment ferais tu la même chose sans Exit ?

Il y a du bon dans toutes les religions...
 
@+
Cirec

<hr size ="2" />
0
Guillemouze Messages postés 991 Date d'inscription samedi 25 octobre 2003 Statut Membre Dernière intervention 29 août 2013 6
17 nov. 2006 à 17:31
moi c'est ce que j'ai fait, et ca marche tres bien. enfin j'ai fait "Xxx.focused := true", mais ca m'etonnerai que ca vienne de la!
En plus, mon objet est assez complexe, car c'est une derivée de TImage qui contient un TWinControl, et j'ai fait

MaTImage = class(TImage)
private
    m_Control: TWinControl;
public
    property CanFocus: Boolean read GetCanFocus
end;

MaTImage.GetCanFocus: Boolean;
begin
    Result := assigned(m_Control) and (m_Control.CanFocus);
end;

avec la meme chose pour les setParent, etc ...

@Loda
ma religion n'est pas si loin de la tienne. le exit en debut de fonction, d'accord. mais le mettre en plein milieu d'un fonction de 200 lignes, je trouve pas ca tres visible au  premier coup d'oeil.
moi je voulai surtout parler des :
for i := 0 to n do
begin
    if tab[i] = nil then
       break;
end;
... pour ne pas utiliser un while. enfin chacun ses gouts.
Je disais juste ca parce qu'il m'est arrivé dernierement d'avoir a relire un fonction de qqun d'autre qui faisait bien 1000 lignes ( !!!! ) et finalement j'ai trouvé un petit exit caché vers la 20eme ligne
0
Guillemouze Messages postés 991 Date d'inscription samedi 25 octobre 2003 Statut Membre Dernière intervention 29 août 2013 6
17 nov. 2006 à 17:51
      Try
        {On alloue suffisement de mémoire}
        GetMem(Buffer, 255);
        {On ouvre le presse-papier}
        OpenClipBoard(0);
        {On récupère le Handle des données}
        Data := GetClipboardData(CF_TEXT);
        If Data <> 0 then // -----  comme ca, non?

        begin
          {On copie les données 255 caractères Max}
          StrLCopy(Buffer, GlobalLock(Data), 255);
          GlobalUnlock(Data);
        end;
      Finally  // -----  ici afin de libérer les objets et la mémoire et ensuite elle quitte la méthode
        {On ferme le presse-papier}
        CloseClipBoard;
        {On libère la mémoire}
        ClpBrd : = String(Buffer);
        FreeMem(Buffer);
      End;

mais j'ai pas dit que ces fonctions n'etaient pas propres. ce que je leur reproche, c'est d'avoir un impact trop important sur le code comparé a leur "visibilité". plus clairement, si tu parcours un bout de code, tu verra pas forcement qu'il y a un exit au milieu, alors que si tu met une condition, l'indentation te permet de mieux voir l'agencement des operations.
enfin je le repete, ce n'est qu'un avis personnel, et je m'en sert quand meme; mais avec tres grande moderation

sur ce, je pense que le sujet est clos? (enfin j'aimearia bien savoir si tu es d'accord avec moi sur le exit dans ton code Cirec)
0
Rejoignez-nous