Problem beim Zeichnen auf Panel bei klassischen Windows Thema



  • Hallo Leute,

    ich habe ein Problem beim Zeichnen von einigen Sachen auf einem TPanel. der folgende Code liegt normalerweise im OnPaint-Ereignis einer Form. Wenn Windows 7 das Aero-Thema hat läuft alles super! Wenn ich aber auf das klassische Thema wechsle, dann zeichnet er es garnicht, sondern nur beim Ziehen des Fensters kann man durch ein Flackern erkennen, dass er die Zeichnung kurz durchführt...

    Wie kommt das? Gibt es ein Workaround dafür?

    Der Code zeichnet mittig in einem TPanel den Fenstertitel, einen Balken daunter und dann 3 Kreise als Logo.

    //-----Im OnPaint-Ereignis der Form
    TCanvas *can = new TCanvas;
    can->Handle=GetDC(OLE_Panel->Handle);
    	can->Font->Size=40;
    	can->Font->Style=TFontStyles()<<fsItalic;
    	SetBkMode(can->Handle,TRANSPARENT);
    	can->Font->Color=clRed;
    	DrawTextW(can->Handle,Form1->Caption.w_str(),Form1->Caption.Length()+1,&TRect(0,0,OLE_Panel->Width-3,OLE_Panel->Height),DT_SINGLELINE | DT_VCENTER|DT_CENTER|DT_END_ELLIPSIS);
    
    	can->Font->Color=clGreen;
    	DrawTextW(can->Handle,Form1->Caption.w_str(),Form1->Caption.Length()+1,&TRect(2,2,OLE_Panel->Width-3,OLE_Panel->Height),DT_SINGLELINE | DT_VCENTER|DT_CENTER|DT_END_ELLIPSIS);
    
    	can->Brush->Color=TColor(0x004080FF);
    	can->FillRect(TRect(OLE_Panel->Width/2+can->TextWidth(Form1->Caption)/2,(OLE_Panel->Height/2)+(can->TextHeight(Form1->Caption)/2),(OLE_Panel->Width/2)-(can->TextWidth(Form1->Caption)/2),(OLE_Panel->Height/2)+(can->TextHeight(Form1->Caption)/2)+10));
    	can->Brush->Color=clSkyBlue;
    	TRect r=TRect(OLE_Panel->Width/2+can->TextWidth(Form1->Caption)/2+2,(OLE_Panel->Height/2)+(can->TextHeight(Form1->Caption)/2)+2,(OLE_Panel->Width/2)-(can->TextWidth(Form1->Caption)/2)+2,(OLE_Panel->Height/2)+(can->TextHeight(Form1->Caption)/2)+12);
    	can->FillRect(r);
    	can->Pen->Color=clWhite;
    	can->Brush->Color=0x004080FF;
    	can->Ellipse(r.Left+5,r.Top-5,r.Left+25,r.top+15);;
    	can->Brush->Color=clSkyBlue;
    	can->Ellipse(r.Left+30,r.Top-5,r.Left+50,r.top+15);;
    	can->Brush->Color=clLime;
    	can->Ellipse(r.Left+55,r.Top-5,r.Left+75,r.top+15);;
    delete can;
    

    Ich habe es auch in der WndProc des Panels in der WM_PAINT Message probiert, aber immer das gleiche.

    Gruß Hawk



  • Hallo Hawkxxx,

    könnte es daran liegen, dass Du das Canvas direkt nach dem Zeichnen mit delete freigibst?

    Leg doch eine PaintBox auf das Panel und zeichne auf dem Canvas der PaintBox.

    Gruß

    Martin



  • Hi,

    also am delete liegt es nicht, ich habe es schon ausprobiert. Auch an den Einstellungen des Panels bei Lock oder FullRepaint oder DoubleBuffering habe ich schon rumprobiert, aber kein Erfolg.

    Mag sein, dass es mit einer PaintBox funktioniert - habe es nicht ausprobiert, aber es muss doch irgendwie direkt mit dem Panel gehen, oder?



  • Zeichne besser im OnPaint des Panels!

    Gruss
    Frank



  • Also ein TPanel hat kein OnPaint-Ereignis. Ich verwende deshalb das WM_PAINT in der abgeleiteten WndProc des Panels. Aber auch dort funktioniert es nicht richtig. Das Resultat bleibt gleich.



  • Hallo
    ich setze für so was ein TImage auf das Panel mit alClient. Ich zeichne auf eine TBitmap und kopiere die Bitmap (bmp) nach dem Zeichnen auf das TImage->Picture->Bitmap=bmp. 🙂

    Grüße Stefan



  • Danke für euer Bemühen. Anscheinend gibt keine Möglichkeit da etwas so zu machen, dass es mit dem klassischen Windows-Thema funktioniert. Ich werde wohl auf die Methode mit dem TImage zurückgreifen, obwohl es nicht ganz so elegant ist.

    Danke!



  • Für sowas ist die PaintBox schon genau richtig.



  • Hawkxxx schrieb:

    Also ein TPanel hat kein OnPaint-Ereignis. Ich verwende deshalb das WM_PAINT in der abgeleiteten WndProc des Panels. Aber auch dort funktioniert es nicht richtig. Das Resultat bleibt gleich.

    ich habe dafür eine Komponente gemacht abgeleitet von TPanel:

    //Header- Datei (.h)
    //---------------------------------------------------------------------------
    #ifndef CanvasPanelH
    #define CanvasPanelH
    //---------------------------------------------------------------------------
    #include <SysUtils.hpp>
    #include <Controls.hpp>
    #include <Classes.hpp>
    #include <Forms.hpp>
    #include <ExtCtrls.hpp>
    //---------------------------------------------------------------------------
    typedef void __fastcall (__closure *TCanvasPanelAfterPaint)(TCanvas *ACanvas,TRect ARect);
    //---------------------------------------------------------------------------
    class PACKAGE TCanvasPanel : public TPanel
    {
    private:
            TCanvasPanelAfterPaint FOnAfterPaint;
            virtual void __fastcall Paint(void);
    protected:
    public:
            __fastcall TCanvasPanel(TComponent* Owner);
    __published:
            __property Canvas;
            __property TCanvasPanelAfterPaint OnAfterPaint={read=FOnAfterPaint,write=FOnAfterPaint};
    };
    //---------------------------------------------------------------------------
    #endif
    
    //CPP- Datei (.cpp)
    //---------------------------------------------------------------------------
    #include <vcl.h>
    #pragma hdrstop
    
    #include "CanvasPanel.h"
    #pragma package(smart_init)
    //---------------------------------------------------------------------------
    // ValidCtrCheck wird benutzt, um sicherzustellen, daß die erzeugten Komponenten keine
    // rein virtuellen Funktionen haben.
    //
    
    static inline void ValidCtrCheck(TCanvasPanel *)
    {
            new TCanvasPanel(NULL);
    }
    //---------------------------------------------------------------------------
    __fastcall TCanvasPanel::TCanvasPanel(TComponent* Owner)
            : TPanel(Owner)
    {
      DoubleBuffered=true;
    }
    //---------------------------------------------------------------------------
    void __fastcall TCanvasPanel::Paint(void)
    {
      TPanel::Paint();
      if (FOnAfterPaint!=NULL)
      { FOnAfterPaint(Canvas,ClientRect);
      }
    }
    //---------------------------------------------------------------------------
    namespace Canvaspanel
    {
            void __fastcall PACKAGE Register()
            {
                     TComponentClass classes[1] = {__classid(TCanvasPanel)};
                     RegisterComponents("Image", classes, 0);
            }
    }
    //---------------------------------------------------------------------------
    

    Damit hast Du:
    1. Zugriff auf Cancas von dem Panel von aussen
    2. ein Ereignis nach dem Zeichnen des Panels selbst.

    das klappt bisher ohne Probleme!

    Gruss
    Frank



  • Hui! Danke für die Mühe!

    Ich werde es demnächst ausprobieren und Bescheid sagen...

    Gruß
    Hawk


Anmelden zum Antworten