Hint-Manipulation, Ableitung der Klasse THintWindow



  • Hi,

    wie zugesagt poste ich hier die Ableitung einer THintWindow-Klasse, die über folgende Eigenschaften verfügt:

    Anzeige des Hint-Textes , in 2 Schriftarten (Überschrift, Text),
    es ist ein Icon positioniert (16 x 16 px),
    runde transparente Ecken,
    einen Pfeil ala BalloonHint.

    Alle Manipulationen finden in der Paint-Routine statt.

    Wichtig ist der Application mitzuteilen, dass sie diese Klasse zu verwenden hat. Dies trägt man in die Projektdatei als sog. Variable ein.
    Der Header der Klassendatei wird includiert.

    Projektdatei ergänzen:

    //---------------------------------------------------------------------------
    #include <vcl.h>
    #pragma hdrstop
    USEFORM("main.cpp", Form1);
    //---------------------------------------------------------------------------
    #include "main.h"       // eintragen, dort steht die neue HintWindow-Klasse
    
    //---------------------------------------------------------------------------
    WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
    {
        try
        {
            Application->Initialize();
            HintWindowClass = __classid(TBHintWindow);          // eintragen
            Application->CreateForm(__classid(TForm1), &Form1);
            Application->Run();
        }
        catch (Exception &exception)
        {
            Application->ShowException(&exception);
        }
        return 0;
    }
    //---------------------------------------------------------------------------
    

    main.h :

    #ifndef mainH
    #define mainH
    //---------------------------------------------------------------------------
    #include <Classes.hpp>
    #include <Controls.hpp>
    #include <StdCtrls.hpp>
    #include <Forms.hpp>
    #include <ComCtrls.hpp>
    //---------------------------------------------------------------------------
    
    class TBHintWindow : public THintWindow
    {
    private:
        POINT     ptArrow[3];
        TImage    *HintImg;
        HFONT     hFont;
        HFONT     hFontBold;
        HRGN      Rgn1;
        HRGN      RgnComb;
        HRGN      RgnArrow;
        HWND      hWnd;
        HDC       hDC;
    
    protected:
       void __fastcall WndProc(Messages::TMessage &Message);
    
    public:
        void __fastcall NCPaint(HDC hDC);
    	__fastcall TBHintWindow(TComponent* AOwner);
    	__fastcall ~TBHintWindow(void);
    __published:
    
    };
    //---------------------------------------------------------------------------
    
    class TForm1 : public TForm
    {
    __published:
    	//IDE-Einträge
    
    private:
    
    public:
    
       TBHintWindow  *TBHWnd;
    
       __fastcall TForm1(TComponent* Owner);
       __fastcall ~TForm1(void);
    };
    //---------------------------------------------------------------------------
    extern PACKAGE TForm1 *Form1;
    //---------------------------------------------------------------------------
    #endif
    

    main.cpp

    #include <vcl.h>
    #pragma hdrstop
    
    #include "main.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    
    // Konstruktor der HintKlasse
    __fastcall TBHintWindow::TBHintWindow(TComponent* AOwner) : THintWindow(AOwner)
    {
       ControlStyle     << csAcceptsControls;
       HintImg = new TImage(this);
       HintImg->Parent  = this;
       HintImg->Left    = 5;
       HintImg->Top     = 40;
       HintImg->Width   = 16;
       HintImg->Height  = 16;
       HintImg->Picture->Bitmap->LoadFromFile("ico.bmp");
    
       hFont = CreateFont( 12, 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET,
       OUT_DEFAULT_PRECIS,
       CLIP_DEFAULT_PRECIS,
       DEFAULT_QUALITY,
       DEFAULT_PITCH | FF_SWISS ,
       "Tahoma" );
    
       hFontBold = CreateFont( 13, 0, 0, 0, FW_BOLD, 0, 0, 0, ANSI_CHARSET,
       OUT_DEFAULT_PRECIS,
       CLIP_DEFAULT_PRECIS,
       DEFAULT_QUALITY,
       DEFAULT_PITCH | FF_SWISS ,
       "Tahoma" );
    }
    //---------------------------------------------------------------------------
    // Destruktor
    __fastcall TBHintWindow::~TBHintWindow()
    {
    	delete HintImg;
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TBHintWindow::WndProc(Messages::TMessage &Message)
    {
    
       switch(Message.Msg) {
          case WM_NCHITTEST : {
             break;
       }
    
       case WM_PAINT: {
          hWnd = this->Handle;
          hDC  = GetDC(hWnd);		
          PAINTSTRUCT ps;
          String HeadLine = "Info:";
          SetMapperFlags( hDC, 1 );
    
          // Caption ist der Hinttext, der im OI eingetippt wurde
          LPCTSTR lpHeadLn = (LPCTSTR) HeadLine.c_str();
          LPCTSTR lpString = (LPCTSTR) Caption.c_str();
    
          // Hintgrösse unter normalen Umständen ermitteln
          //----------------------------------------------
          TRect rect;
          rect   = CalcHintRect( 400, Caption, NULL);
          // Grösse des HintFenster je nach Captionlänge +
          // Distanzen für Icon etc. festlegen
          SetBounds( Left - 20, Top -20, rect.Right + 50, rect.Bottom + 80);
    
          // Pfeil
          ptArrow[0] = Point(10, 30);
          ptArrow[1] = Point(20,  0);
          ptArrow[2] = Point(30, 30);
    
          RgnComb   = CreateRectRgn( 0, 0, 10, 10 );   // Dummy
          Rgn1 = CreateRoundRectRgn( 0, 30, rect.Right + 50, rect.Bottom + 80, 15, 15 );
          RgnArrow  = CreatePolygonRgn( ptArrow, sizeof(ptArrow)/sizeof(POINT), ALTERNATE );
          CombineRgn( RgnComb, Rgn1, RgnArrow, RGN_OR );
    
          SetWindowRgn(hWnd, RgnComb, true);
    
          BeginPaint( hWnd, &ps );
          SetBkMode( hDC, TRANSPARENT );
          RECT rcHeadLine;
          SetRect( &rcHeadLine, 30, 35, rect.Right, rect.Top + 80 );
          SelectObject( hDC, hFontBold );
          DrawText( hDC, lpHeadLn, -1, &rcHeadLine, DT_LEFT | DT_TOP );
    
          RECT rcText;
          SetRect( &rcText, 30, 50, rect.Right + 20, rect.Bottom + 80 );
          SelectObject( hDC, hFont );
          DrawText( hDC, lpString, -1, &rcText,  DT_WORDBREAK	 | DT_LEFT | DT_TOP );
    
          EndPaint( hWnd, &ps );
          HintImg->Repaint();
          // SetWindowRgn bewirkt, dass die Region ausserhalb der
          // runden Eckbereiche transparent sind
    
          DeleteObject( RgnArrow );
          DeleteObject( Rgn1 );
          DeleteObject( RgnComb );
          ReleaseDC( hWnd, hDC );
    
          break;
          }
          case WM_ERASEBKGND  : {
             SetWindowRgn(hWnd, RgnComb, false);
    	 break;
          }
          default:
                break;
       }
       THintWindow::WndProc(Message);
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TBHintWindow::NCPaint(HDC hDC)
    {
       // leere Funktion, ohne die im BCB2009 der Compiler mault...
    }
    
    //---------------------------------------------------------------------------
    
    __fastcall TForm1::TForm1(TComponent* Owner)
    	: TForm(Owner)
    {
       TBHWnd    = new TBHintWindow(this);
    }
    //---------------------------------------------------------------------------
    
    __fastcall TForm1::~TForm1()
    {
        delete TBHWnd;
    }
    //---------------------------------------------------------------------------
    

    Fragen/Kritik/Anregungen gerne gesehen.

    mfg
    kpeter



  • #include "main.h" // eintragen, dort steht die neue HintWindow-Klasse

    M.E. reicht einfach eine Vorwärtsdeklaration, d.h.

    class TBHintWindow;
    

    Evtl. könntest du die Klasse noch mit Properties ausstatten, um z.B. Icon, Font, Positionen etc. zu setzen (anstatt daß jeder Anwender selber direkt den SourceCode ändern muß).



  • Th69 schrieb:

    #include "main.h" // eintragen, dort steht die neue HintWindow-Klasse

    M.E. reicht einfach eine Vorwärtsdeklaration, d.h.

    class TBHintWindow;
    

    Hi,

    der include-Eintrag war mir auch nicht suspekt. Habe ihn rausgenommen und die Variable

    HintWindowClass = __classid(TBHintWindow);
    

    in den Konstruktor von Form1 eingetragen. So geht es auch.

    Dein anderer Vorschlag geht in Richtung Entwurfzeitschnittstelle, sprich Komponente.
    Da lohnte sich ein HintManager für alle der Anwendung untergeordneten Komponenten.
    Die Hints in einem Rutsch verwalten.
    Während der Laufzeit müsste man "nur" den Sender des Hints herausfinden und könnte
    das Design anpassen...

    Kann man drüber nachdenken.

    Der Thread hier hat übrigens eine "Vorgeschichte", s. hier :
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-240840.html

    mfg
    kpeter


Anmelden zum Antworten