TMainMenu im Canvas zeichnen (Kopfzeile)



  • Hallo,

    ich zeichnen mein komplettes Menü selbst, klappt auch wunderbar.

    Nur die Kopfzeile bekomme ich nicht komplett gezeichnet, sondern nur
    den Bereich, in dem die Menütexte stehen. Der Rest der Menüzeile
    bis zum rechten Rand bleibt in der Farbe clBtnFace. Wie komme ich da
    aber zum Zeichnen ran? Die Komponente bietet keine Funktion OnDrawItem
    oder so wie die Menüeinträge selbst.

    Danke für jeden Tip. Im Google und hier finde ich leider nichts oder
    ich suche falsch.... 😉

    Gruss Stefan



  • Du mußt einfach mit Canvas->FillRect() den Hintergrund erst "leeren" (vorher Farbe mit Brush->Color setzen) und danach dann den Menu-Text zeichnen.

    Schau dir mal die Eigenschaft Brush->Style an, dann findest du weitere Infos (evtl. kommt dann bei dir der AHA-Effekt).



  • Hallo, TH

    ich fürchte nicht ganz. Die Menüs werden ja korrekt gezeichnet, aber eben nur die Fläche, wo auch in der Menüzeile (Datei, Bearbeiten... Hilfe) ein Menütext steht. Es geht aber um die restliche Fläche rechts daneben (also ab dem Menü Hilfe bis zum rechten Rand des Forms), für den ich keine Meldung erhalte, daß er neu gezeichnet werden muss, obwohl dieser Bereich ja zum TMainMenu gehört (oder nicht?) Die Komponente TMainMenu hat aber kein Ereignis OwnerDraw, sondern nur die Menüs selbst.

    Gruss Stefan



  • Zeig mal deinen Code von OnDrawItem...

    Du kannst das Rechteck auch selbst wählen, d.h. du brauchst nicht unbedingt den übergebenen Rect-Parameter 1:1 übernehmen (vergrößere doch einfach das Rechteck ein bißchen nach rechts (nur für die Hautpmenü-Einträge), bevor du den Hintergrund und den Text zeichnest).

    P.S: ich habe gerade deinen Beitrag zum TabControl gelesen. Dort verwendest du ja auch das übergebene Rechteck (kopierst es sogar unnötigerweise). Und dann kannst du es aber genausogut vergrößern (z.B. mit Rect.Right = 800 ).



  • Hei, TH

    danke für Deine Tipps...

    Die Kopie auf Rect ist notwendig wegen DrawText; sonst kommt Meldung das Mehrdeutigikeit zwischen 'Rect' und 'tabRet*' besteht. Mit der scheinbaren
    Übergabe auf CRect funktioniert es. 😕

    Mit der RECT Vergrösserung werde ich mir anschauen, sehe aber ein Problem:
    Die Verlängerung der RECT wäre ja beim Menü Hilfe notwendig; wird aber nur rechts
    ein Teil des Forms überlappt, kommt keine OnDraw Meldung, da das Menü Hilfe nicht neugezeichnet werden würde/müsste. Wozu gehört denn die Fläche rechts daneben?

    Aber für alle mal hier den Code zum Selbstzeichnen eines Menüs:
    Dazu TMainMenu auf OwnerDraw=true setzen und jedem (!) Menüeintrag bei OnDrawItem=Bearbeiten1AdvancedDrawItem() zuordnen. PrgFarbe ist ein
    Integerwert z.B. PrgFarbe=clBtnFace

    void __fastcall TForm1::Bearbeiten1AdvancedDrawItem(TObject *Sender, TCanvas *ACanvas, TRect &ARect, TOwnerDrawState State)
    {try {                                                                          // Fehlerroutine Start
     Integer i2,iSymb; AnsiString z1,z2; TColor f1,f2; Boolean o1;                  // Vars definieren
    
     TMenuItem *CurItem = dynamic_cast<TMenuItem *> (Sender);                       // Versuchen, Sender als MenuItem anzusprechen
     if (!CurItem) { return; }                                                      // Wenn Versuch nicht erfolgreich, dann raus
    
     z1=CurItem->Caption;                                                           // Menübeschriftung
     z2=ShortCutToText(CurItem->ShortCut);                                          // Tastenkombination z.B. Alt+F4
    
     f1=PrgFarbe; if(State.Contains(odSelected)==true) { f1=clMenuHighlight; }      // HG Farbe
     ACanvas->Brush->Color=f1;                                                      // Farbe HG festlegen
     ACanvas->FillRect(ARect);                                                      // HG befüllen
    
     if(z1=="-") {                                                                  // TRENNSTRICH
      ARect.Top+=1; ARect.Bottom-=3;                                                // Strich dünner machen
      ACanvas->Brush->Color=clGray;                                                 // Farbe HG festlegen
      ACanvas->Font->Color =clWhite;                                                // Farbe VG festlegen
      ACanvas->FrameRect(ARect);                                                    // dünnen Balken zeichnen
      return;                                                                       // und fertig
     }                                                                              // ende if(z1
    
     f1=PrgFarbe;   if(State.Contains(odSelected)==true) { f1=clMenuHighlight; }    // HG Farbe
     f2=clMenuText; if(State.Contains(odDisabled)==true) { f2=clGrayText; }         // VG Farbe
    
     o1=false;                                                                      // Voreinstellung
     if(CurItem->Tag==9999) { ARect.Left-=20; ARect.Right+=25; ARect.Top+=1; o1=true; } // Hauptmenüthema (immer linksbündig schreiben da keine Symbole)
    
     iSymb=CurItem->ImageIndex;                                                     // Grafiksymbol?
     if(State.Contains(odChecked)==true) { iSymb=58; }                              // Eintrag hat vorne einen Haken
    
     if(Form1->PrgComp && o1==false) { z1=z1+" (iSymb: "+IntToStr(iSymb)+")"; }     // nur im IDE
     if(iSymb>-1) {                                                                 // ja, vorhanden
      Graphics::TBitmap *bmp =new Graphics::TBitmap();                              // neue Grafik anlegen
      frm1_ImageList1->GetBitmap(iSymb,bmp);                                        // und aus Imageliste auslesen
      ACanvas->Draw(1,ARect.Top+1,bmp);                                             // und  zeichnen
      delete bmp;                                                                   // Bitmap löschen
     }                                                                              // ende if(iSymb
    
     ARect.Left+=25; ARect.Right-=25;                                               // Koords anpassen wegen Symbole
     ARect.Top+=2; ARect.Bottom-=2;                                                 // Text x Pixel tiefer setzen
    
     ACanvas->Brush->Color=f1;                                                      // Farbe HG festlegen
     ACanvas->Font->Color =f2;                                                      // Farbe VG festlegen
    
     z1=z1+"  ";                                                                    // damit Abstand zu ShortCuts grösser wird
     DrawText(ACanvas->Handle,z1.c_str(),-1,&ARect,DT_LEFT  | DT_SINGLELINE);       // Menütext z.B. Beenden
     if(z2.Length()==0) { return; }                                                 // keine Tastenkombination mehr, fertig
    
     ARect.Right+=14;                                                               // mehr nach rechts rücken
     DrawText(ACanvas->Handle,z2.c_str(),-1,&ARect,DT_RIGHT | DT_SINGLELINE);       // Tastenkombination z.B. Alt+F4
    
     } catch(Exception& e) { MessageBox(NULL, e.Message.c_str(), "TForm1::Datei1DrawItem()", MB_OK); }  // Fehler anzeigen
    }
    

    Gruss Stefan



  • Wozu gehört denn die Fläche rechts daneben?

    Die Menüleiste selbst wird von Windows gemalt (der sogenannte NonClient-Bereich (NC area)). Da müßtest du schon mit Windows-Messages dran, um diese komplett selbst zu zeichnen.



  • Hei, TH

    habe jetzt eine einfache Lösung gefunden:
    Ein leeres Pseudomenü angehängt (nach Hilfe), den TAG auf 9998
    gesetzt und dies im OnDrawMenü angefangen; RECT.Right auf Screen->Width
    gesetzt, Menü Disabled und voila, funktioniert einwandfrei 🙂

    Gruss Stefan



  • Na, geht doch 😉


Anmelden zum Antworten