Fenêtres, la tête sur le côté

fouffouf Membre
18:56 modifié dans API AppKit #1
Est-ce quelqu'un sait comment faire des NSPanel avec la barre de titre sur le côté ?

Réponses

  • Eddy58Eddy58 Membre
    18:56 modifié #2
    Et bien Cocoa ne propose pas une telle possibilité (enfin pas à  ma connaissance), et je pense que le seul moyen est de customiser ton panel en le sous-classant et de récupérer les mouse events pour le dragging. Je dis pas que c'est simple et que c'est la meilleure solution, mais voici ce que je ferais : :)
    1) Sous IB, faire un NSPanel, et le sous-classer. Mettre une CustomView sur la gauche de la fenêtre, qui serait à  l'endroit ou serait positionnée ta barre de fenêtre verticale.
    2) Dans X-Code, dans le code de ta sous-classe du NSPanel, tu recouvres la méthode d'initialisation de la fenêtre initWithContentRect:styleMask:backing:defer, avec un styleMask de valeur NSBorderlessWindowMask.
    3) Tu met dans ta CustomView une image de la barre de titre, dont tu as fait faire auparavant une rotation de 90° dans ton soft de 2D préféré (Seashore ? ;)).
    4) Il ne "te reste plus" qu'à  recouvrir les mouse events dans la sous-classe de ton NSPanel, en détectant quand le bouton de souris est cliqué sur la barre de titre (mouseDown), et ensuite en recalculant la position de ton panel en recouvrant mouseDragged. Pareil pour l'action de miniaturisation, tu peux jouer avec mouseDown.

  • fouffouf Membre
    18:56 modifié #3
    Ok, merci beaucoup, je vais essayer de m'y mettre après avoir réglé mon pb de régles. Je ferais une sous-classe histoire d'en faire profiter tout le monde.
  • BruBru Membre
    avril 2005 modifié #4
    C'est un peu bête de devoir recréer de toute pièce une telle fenêtre, alors que ce style (fenêtre flottante avec barre de titre sur le côté) existe déjà  sous Mac OS.

    Par contre, il faut passer par Carbon (création d'une fenêtre par la fonction CreateNewWindow). Le mieux est donc de créer cette fenêtre via Carbon, puis ensuite de l'attacher à  une NSWindow/NSPanel via la méthode initWithWindowRef:

    exemple (à  tester) :
    [tt]
    {
        OSStatus err;
        WindowRef carbonWnd;
        Rect r;
        NSWindow *cocoaWnd;

        r.top=0;
        r.left=0;
        r.bottom=100;
        r.right=100;
        err=CreateNewWindow(kFloatingWindowClass,
                            kWindowSideTitlebarAttribute+kWindowStandardFloatingAttributes
                                + kWindowStandardHandlerAttribute,
                            &r,
                            &carbonWnd);
        if (err==noErr)
        {
            cocoaWnd=[[NSWindow alloc] initWithWindowRef:carbonWnd];
            [cocoaWnd makeKeyAndOrderFront:nil];
        }
    }
    [/tt]
    .
  • fouffouf Membre
    18:56 modifié #5
    Ouais, super, j'essaye ca ce soir (enfin, je fais ce que je peux)
  • fouffouf Membre
    18:56 modifié #6
    Bru, t'es un dieu.  o:) o:) o:) <3 <3 <br />
    Ca marche super, si ce n'est qu'il faut remettre une bonne frame. Voila.

    Encore merci.
  • fouffouf Membre
    18:56 modifié #7
    Argh !!!
    J'ai quand même un pb : je voudrais mettre une content view à  la fenêtre en question. Bon, elle s'affiche mais impossible de cliquer sur un bouton par exemple. Que se passe-t-il ?
  • BruBru Membre
    18:56 modifié #8
    dans 1114200772:

    Argh !!!
    J'ai quand même un pb : je voudrais mettre une content view à  la fenêtre en question. Bon, elle s'affiche mais impossible de cliquer sur un bouton par exemple. Que se passe-t-il ?


    En fait, je ne sais pas si on peut mélanger des NSViews (cocoa) et des HIViews (carbon).

    Je ne sais pas à  quoi va servir cette fenêtre, mais le mieux est de la créer dans IB (menu File>New>Carbon>Window), puis de la gérer dans ton programme via les apis carbon ad'hoc.

    .
  • fouffouf Membre
    avril 2005 modifié #9
    dans 1114330378:

    En fait, je ne sais pas si on peut mélanger des NSViews (cocoa) et des HIViews (carbon).

    Je ne sais pas à  quoi va servir cette fenêtre, mais le mieux est de la créer dans IB (menu File>New>Carbon>Window), puis de la gérer dans ton programme via les apis carbon ad'hoc.


    C'est ce que je pensais faire. Ecoutes, je teste, et je te tiens au courant.

    [edit]
    Non non et non.

    Je faire faire la méthode de Favouille puis je ferais une sous-classe (une palette) pour OC.

    Merci quand même Bru.
  • Eddy58Eddy58 Membre
    18:56 modifié #10
    dans 1114359676:

    Je faire faire la méthode de Favouille puis je ferais une sous-classe (une palette) pour OC.

    Non non c'est moi je crois plus haut. ;)

    Peut-être un autre truc à  essayer avec la méthode de Bru, c'est en effet de faire un Panel via carbon, et ensuite au lieu de mettre une view dedans, tu surveilles les mouvements de ce panel avec une notification, et tu pourrais calquer les coordonnées d'une fenêtre cocoa NSBorderless avec la view voulue dedans, sur les coordonnées du panel carbon... :)
  • ClicCoolClicCool Membre
    18:56 modifié #11
    dans 1114423736:

    dans 1114359676:

    Je faire faire la méthode de Favouille puis je ferais une sous-classe (une palette) pour OC.

    Non non c'est moi je crois plus haut. ;)


    mdr
    quand c'est pas moi qui dit Eddy au lieu de Fouf, c'est Fouf qui dit Favouille au lieu d'Eddy  ;D

    Ceci dit, si tu optes pour l'iddée d'Eddy d'un panel sans titre avec un titre simulé sur un bord, essaies, plutôt que de te casser la tête à  détecter les drag sur ton faux titre, d'utiliser:

    - (BOOL)isMovableByWindowBackground
    de NSWindow qui permet quand on renvoie YES d'avoir une fenêtre qu'on peut déplacer en cliquant sur son fond (façon textured window)

    combiné avec:

    - (BOOL)mouseDownCanMoveWindow
    de NSView qui te permettra de laisser le clic-drag sur ta vue de titre "traverser" la vue et bouger alors la fenêtre comme si tu la manipulais avec son fond ...
    Tu peux aussi couvrir le reste du contenu de la fenêtre avec une vue qui elle interdira qu'on bouge ta palette autrement que par son faut titre ...

    ça me parrait plus simple comme ça ;)
  • fouffouf Membre
    18:56 modifié #12
    Excuse moi Eddy.  o:)

    Eddy, trop compliqué ta 2eme méthode. C'est de la bidouille.  B)

    @ClicCool
    - (BOOL)isMovableByWindowBackground marche nickel. Par contre, je n'arrive pas à  me débrouiller pour que le reste de la fenêtre ne puisse pas servir de zone de déplacement. Remarque, c'est pas grave.

    Merci encore les mecs. Je vous informe de l'avancement.
  • BruBru Membre
    18:56 modifié #13
    Y'a des attitudes que parfois je ne pige pas...

    Au lieu d'utiliser ce qui existe et qui fonctionne (si on sait faire...), et ben, non, on refait tout (quitte à  faire moins bien, moins évolutif, et surtout, moins compatible avec les évolutions du OSX).

    Bon, je vais regarder cette histoire de fenêtre carbon dans un prog cocoa et je mettrais ici les résultats de mes recherches.

    .
  • fouffouf Membre
    18:56 modifié #14
    :'( :'( :'(
    On ne peut pas  :'(

    On ne peut pas mettre des éléments et récupérer leurs actions quand on utilise NSBordlessWindowMask.

    @Bru
    Ne te faches pas. Je ne connais pas Carbon du tout. Et après deux jours de bidouilles diverses et variées j'ai abandonné. Voila tout. Sinon, si tu proposes une solution qui me permet d'utiliser des NSView, je suis preneur

    Encore merci  o:)
  • ClicCoolClicCool Membre
    18:56 modifié #15
    dans 1114439325:

    @ClicCool
    - (BOOL)isMovableByWindowBackground marche nickel. Par contre, je n'arrive pas à  me débrouiller pour que le reste de la fenêtre ne puisse pas servir de zone de déplacement. Remarque, c'est pas grave.


    ben il me semble que t'as qu'à  couvrir le reste de ta fenêtre avec une NSView de "fond" qui répond "non" à  mouseDownCanMoveWindow ... ?
    En fait j'ai jamais essayé mais y'a pas d'raison.

    dans 1114451096:

    Y'a des attitudes que parfois je ne pige pas...


    T'as raison Bru mais j'y connais pas grand chose à  Carbon et voyant qu'on s'orientait vers une fenêtre cocoa bidouillée il me semble que l'usage des méthodes que j'ai proposées simplifie grandement les choses.

    C'est sur que si t'enrrichis OC d'une ressource permetant ce genre de résultat proprement ce sera top !
    Ceci dit reconnais que ça n'est pas simple (sinon t'aurais donné la solution avant même que la question soit posée).
  • BruBru Membre
    18:56 modifié #16
    Bon, je vous donne une solution.

    Ele vaut ce qu'elle vaut mais elle permet de gérer une fenêtre Carbon dans un prog Cocoa.

    La fenêtre est faite sous IB (file>new...>Carbon>Window). Le nib se nomme carbonwindow.nib et se trouve dans le groupe Resources du projet Cocoa. La fenêtre a pour titre Window, et contient un bouton dont le code commande (Button info>Control>Command) est btok (en fait il s'agit d'un entier 32 bits dont la reprséentation ascii est btok).

    Tout le code de gestion de cette fenêtre est mise dans le controleur (nom ctl) du MainMenu.nib du projet Cocoa.

    .
  • BruBru Membre
    18:56 modifié #17
    Voici le ctl.h :

    <br />#import &lt;Cocoa/Cocoa.h&gt;<br />#import &lt;Carbon/Carbon.h&gt;<br /><br /><br />@interface ctl : NSObject<br />{<br />	NSWindow *cocoaFromCarbonWin;<br />}<br />@end<br />
    


    .
  • BruBru Membre
    avril 2005 modifié #18
    et le ctl.m

    <br />#import &quot;ctl.h&quot;<br /><br />// diverses déclarations C<br />EventTypeSpec commSpec={kEventClassCommand, kEventProcessCommand};<br />pascal OSStatus CarbonWindowCommandHandler(EventHandlerCallRef handlerRef,<br />                                     &nbsp;     EventRef event, void *userData);<br /><br />// déclaration des méthodes privées de ctl.<br />@interface ctl(Private)<br />+ (void)_HIControlAction:(UInt32)controlID;<br />- (NSWindow *)_loadAndDisplayCarbonWindow;<br />@end<br /><br />@implementation ctl<br /><br />// méthode de classe appellée sur action d&#39;un contrôle carbon.<br />+ (void)_HIControlAction:(UInt32)controlID<br />{<br />    if (controlID==&#39;btok&#39;) NSLog(@&quot;bouton OK appuyé&quot;);<br />}<br /><br />// nib cocoa chargé : on affiche la fenêtre carbon.<br />- (void)awakeFromNib<br />{<br />    cocoaFromCarbonWin=[self _loadAndDisplayCarbonWindow];<br />}<br /><br />// méthode privée chargeant et affichant une fenêtre carbon.<br />// renvoie le NSWindow* de la fenêtre carbon (nil si erreur).<br />- (NSWindow *)_loadAndDisplayCarbonWindow<br />{<br />    CFBundleRef bundleRef;<br />    IBNibRef nibRef;<br />    OSStatus err;<br />    WindowRef carbonWindow;<br />    NSWindow *cocoaWindow;<br /><br />    cocoaWindow=nil;<br /><br />    // chargement du nib carbon.<br />    bundleRef=CFBundleGetMainBundle();<br />    err=CreateNibReferenceWithCFBundle(bundleRef, CFSTR(&quot;carbonwindow&quot;), &amp;nibRef);<br />    CFRelease(bundleRef);<br />    if (err!=noErr) return nil;<br /><br />    // chargement de la fenêtre carbon.<br />    err=CreateWindowFromNib(nibRef, CFSTR(&quot;Window&quot;), &amp;carbonWindow);<br />    DisposeNibReference (nibRef);<br />    if (err!=noErr) return nil;<br /><br />    // installation de la procédure de gestion des événements carbon.<br />    InstallWindowEventHandler(carbonWindow, NewEventHandlerUPP(CarbonWindowCommandHandler),<br />                               1, &amp;commSpec, (void *)carbonWindow, NULL);<br /><br />    // création de la fenêtre cocoa équivalente et affichage.<br />    cocoaWindow=[[NSWindow alloc] initWithWindowRef:carbonWindow];<br />    [cocoaWindow makeKeyAndOrderFront:nil];<br /><br />    return cocoaWindow;<br />}<br /><br />@end<br /><br />// fonction appellée par le carbon-control-manager<br />pascal OSStatus CarbonWindowCommandHandler(EventHandlerCallRef handlerRef,<br />                                     &nbsp;     EventRef event, void *userData)<br />{<br />    HICommand command; <br /><br />    // récupération de l&#39;ID du contrôle.<br />    GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &amp;command );<br /><br />    // appel de la méthode de classe du contrôleur.<br />    [ctl _HIControlAction:command.commandID];<br />    return 0;<br />}<br />
    


    .
Connectez-vous ou Inscrivez-vous pour répondre.