usercontrol



  • Hallo Forum,
    ich brauche dringend (aus historischen Gründen) ein 7 Segmentelementdisplay auf c++/cli (VS 2008) Basis und habe daher ein solches Beispiel einfach kurzer Hand mal umgeschrieben(https://www.codeproject.com/Articles/37800/Seven-segment-LED-Control-for-NET).

    #pragma once
    
    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;
    using namespace System::Drawing::Drawing2D;
    
    namespace SevenSegment {
    
    	/// <summary>
    	/// Zusammenfassung für SingleSegment
    	/// </summary>
    	public ref class SingleSegment : public System::Windows::Forms::UserControl
    	{
    
    	public: 	array<System::Drawing::Point^,2>^ segPoints;
    	public:     array<System::Drawing::Point>^ copiedsegPoints;
    
    	public:
    
    		SingleSegment(void)
    		{
    			InitializeComponent();
                this->SuspendLayout();
                this->Name = "SevenSegment";
    
    			this->Size = System::Drawing::Size(32, 64);
    
    			this->Paint += gcnew System::Windows::Forms::PaintEventHandler(this, &SingleSegment::SevenSegment_Paint);
    			this->Resize += gcnew System::EventHandler(this, &SingleSegment::SevenSegment_Resize);
                this->ResumeLayout(false);
    
                this->TabStop = false;
    
    			this->Padding = System::Windows::Forms::Padding(4, 4, 4, 4);
    
    			this->DoubleBuffered = true;
    
                segPoints = gcnew array<System::Drawing::Point^,2> (7,7);
    
    			for (int i = 0; i < 7; i++)  {for (int j = 0; j < 7; j++) segPoints[i,j] = gcnew Point(0,0);
    																	//  copiedsegPoints[i] =Point(0,0);
    			}
    
    			copiedsegPoints = gcnew array<System::Drawing::Point>(6);
    
                RecalculatePoints();
    		}
    
    	protected:
    		/// <summary>
    		/// Verwendete Ressourcen bereinigen.
    		/// </summary>
    		~SingleSegment()
    		{
    			if (components)
    			{
    				delete components;
    			}
    		}
    
    	private:
    		/// <summary>
    		/// Erforderliche Designervariable.
    		/// </summary>
    		System::ComponentModel::Container ^components;
    
    #pragma region Windows Form Designer generated code
    		/// <summary>
    		/// Erforderliche Methode für die Designerunterstützung.
    		/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
    		/// </summary>
    		void InitializeComponent(void)
    		{
    			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
    		}
    #pragma endregion
    
            /// <summary>
            /// Recalculate the points that represent the polygons of the
            /// seven segments, whether we're just initializing or
            /// changing the segment width.
            /// </summary>
    	private: 
    		void RecalculatePoints()
            {
                int halfHeight = gridHeight / 2, halfWidth = elementWidth / 2;
    
                int p = 0;
                segPoints[p,0]->X = elementWidth + 1; segPoints[p,0]->Y = 0;
                segPoints[p,1]->X = gridWidth - elementWidth - 1; segPoints[p,1]->Y = 0;
                segPoints[p,2]->X = gridWidth - halfWidth - 1; segPoints[p,2]->Y = halfWidth;
                segPoints[p,3]->X = gridWidth - elementWidth - 1; segPoints[p,3]->Y = elementWidth;
                segPoints[p,4]->X = elementWidth + 1; segPoints[p,4]->Y = elementWidth;
                segPoints[p,5]->X = halfWidth + 1; segPoints[p,5]->Y = halfWidth;
    
                p++;
                segPoints[p,0]->X = 0; segPoints[p,0]->Y = elementWidth + 1;
                segPoints[p,1]->X = halfWidth; segPoints[p,1]->Y = halfWidth + 1;
                segPoints[p,2]->X = elementWidth; segPoints[p,2]->Y = elementWidth + 1;
                segPoints[p,3]->X = elementWidth; segPoints[p,3]->Y = halfHeight - halfWidth - 1;
                segPoints[p,4]->X = 4; segPoints[p,4]->Y = halfHeight - 1;
                segPoints[p,5]->X = 0; segPoints[p,5]->Y = halfHeight - 1;
    
                p++;
                segPoints[p,0]->X = gridWidth - elementWidth; segPoints[p,0]->Y = elementWidth + 1;
                segPoints[p,1]->X = gridWidth - halfWidth; segPoints[p,1]->Y = halfWidth + 1;
                segPoints[p,2]->X = gridWidth; segPoints[p,2]->Y = elementWidth + 1;
                segPoints[p,3]->X = gridWidth; segPoints[p,3]->Y = halfHeight - 1;
                segPoints[p,4]->X = gridWidth - 4; segPoints[p,4]->Y = halfHeight - 1;
                segPoints[p,5]->X = gridWidth - elementWidth; segPoints[p,5]->Y = halfHeight - halfWidth - 1;
    
                p++;
                segPoints[p,0]->X = elementWidth + 1; segPoints[p,0]->Y = halfHeight - halfWidth;
                segPoints[p,1]->X = gridWidth - elementWidth - 1; segPoints[p,1]->Y = halfHeight - halfWidth;
                segPoints[p,2]->X = gridWidth - 5; segPoints[p,2]->Y = halfHeight;
                segPoints[p,3]->X = gridWidth - elementWidth - 1; segPoints[p,3]->Y = halfHeight + halfWidth;
                segPoints[p,4]->X = elementWidth + 1; segPoints[p,4]->Y = halfHeight + halfWidth;
                segPoints[p,5]->X = 5; segPoints[p,5]->Y = halfHeight;
    
                p++;
                segPoints[p,0]->X = 0; segPoints[p,0]->Y = halfHeight + 1;
                segPoints[p,1]->X = 4; segPoints[p,1]->Y = halfHeight + 1;
                segPoints[p,2]->X = elementWidth; segPoints[p,2]->Y = halfHeight + halfWidth + 1;
                segPoints[p,3]->X = elementWidth; segPoints[p,3]->Y = gridHeight - elementWidth - 1;
                segPoints[p,4]->X = halfWidth; segPoints[p,4]->Y = gridHeight - halfWidth - 1;
                segPoints[p,5]->X = 0; segPoints[p,5]->Y = gridHeight - elementWidth - 1;
    
                p++;
                segPoints[p,0]->X = gridWidth - elementWidth; segPoints[p,0]->Y = halfHeight + halfWidth + 1;
                segPoints[p,1]->X = gridWidth - 4; segPoints[p,1]->Y = halfHeight + 1;
                segPoints[p,2]->X = gridWidth; segPoints[p,2]->Y = halfHeight + 1;
                segPoints[p,3]->X = gridWidth; segPoints[p,3]->Y = gridHeight - elementWidth - 1;
                segPoints[p,4]->X = gridWidth - halfWidth; segPoints[p,4]->Y = gridHeight - halfWidth - 1;
                segPoints[p,5]->X = gridWidth - elementWidth; segPoints[p,5]->Y = gridHeight - elementWidth - 1;
    
                p++;
                segPoints[p,0]->X = elementWidth + 1; segPoints[p,0]->Y = gridHeight - elementWidth;
                segPoints[p,1]->X = gridWidth - elementWidth - 1; segPoints[p,1]->Y = gridHeight - elementWidth;
                segPoints[p,2]->X = gridWidth - halfWidth - 1; segPoints[p,2]->Y = gridHeight - halfWidth;
                segPoints[p,3]->X = gridWidth - elementWidth - 1; segPoints[p,3]->Y = gridHeight;
                segPoints[p,4]->X = elementWidth + 1; segPoints[p,4]->Y = gridHeight;
                segPoints[p,5]->X = halfWidth + 1; segPoints[p,5]->Y = gridHeight - halfWidth;
    
            }
    
    			static int gridHeight = 80;
    			static int gridWidth = 48;
    			static int elementWidth = 10;
    			static float italicFactor = 0.0F;
    			static System::Drawing::Color colorBackground = System::Drawing::Color::DarkGray;
    			static System::Drawing::Color colorDark = System::Drawing::Color::DimGray;
    			static System::Drawing::Color colorLight = System::Drawing::Color::Red;
    
            /// <summary>
            /// Background color of the 7-segment display.
            /// </summary>
    		public:
    		property	System::Drawing::Color ColorBackground { 
    																	System::Drawing::Color get() { 
    																					return  colorBackground; 																				
    																				}
    																	void set(System::Drawing::Color  value) { 
    																					colorBackground = value; 
    																					this->Invalidate(); 
    																	} 
    													 }
            /// <summary>
            /// Color of inactive LED segments.
            /// </summary>
            property System::Drawing::Color ColorDark { 
    																	System::Drawing::Color get() { 
    																					return   colorDark; 																				
    																				}
    																	void set(System::Drawing::Color  value) { 
    																					colorDark = value; 
    																					this->Invalidate(); 
    																	} 
    													 }
    
            /// <summary>
            /// Color of active LED segments.
            /// </summary>
            property	System::Drawing::Color ColorLight { 
    																	System::Drawing::Color get() { 
    																					return    colorLight; 																				
    																				}
    																	void set(System::Drawing::Color  value) { 
    																					colorLight = value; 
    																				this->Invalidate(); 
    																	} 
    													 }
    
            /// <summary>
            /// Width of LED segments.
            /// </summary>
            property int ElementWidth { 
    																	int get() { 
    																					return  elementWidth; 																				
    																				}
    																	void set(int value) { 
    
    																					elementWidth = value; 
    																					RecalculatePoints(); 
    																					this-> Invalidate();
    																	} 
    													 }
    
            /// <summary>
            /// Shear coefficient for italicizing the displays. Try a value like -0.1.
            /// </summary>
            property float ItalicFactor { 
    																	float get() { 
    																					return  italicFactor; 																				
    																				}
    																	void set(float value) { 
    																					italicFactor = value; 
    																					this->Invalidate();
    																	} 
    													 }
    
    	   private: 
    		   void SevenSegment_Resize(Object^ sender, EventArgs^ e) { this->Invalidate(); }
    
    	   protected: 
    		   virtual  void OnPaddingChanged(EventArgs^ e) override { 
    			   //base::OnPaddingChanged(e); 
    	           this->Invalidate(); 
    		   } 
    
    			virtual void OnPaintBackground(PaintEventArgs^ e) override
    			{
    			//base::OnPaintBackground(e);
                e->Graphics->Clear(colorBackground);
    			}
    
            /// <summary>
            /// These are the various bit patterns that represent the characters
            /// that can be displayed in the seven segments. Bits 0 through 6
            /// correspond to each of the LEDs, from top to bottom!
            /// </summary>
    	 public:
            enum class ValuePattern
            {
                None = 0x0, 
    			Zero = 0x77, 
    			One = 0x24, 
    			Two = 0x5D, 
    			Three = 0x6D,
                Four = 0x2E, 
    			Five = 0x6B, Six = 0x7B, Seven = 0x25,
                Eight = 0x7F, Nine = 0x6F, A = 0x3F, B = 0x7A, C = 0x53,
                D = 0x7C, E = 0x5B, F = 0x1B, G = 0x73, H = 0x3E,
                J = 0x74, L = 0x52, N = 0x38, O = 0x78, P = 0x1F, Q = 0x2F, R = 0x18,
                T = 0x5A, U = 0x76, Y = 0x6E,
                Dash = 0x8, Equals = 0x48
            } ;
    
    		private:
    			static String^ theValue = "";
    
            /// <summary>
            /// Character to be displayed on the seven segments. Supported characters
            /// are digits and most letters.
            /// </summary>
    		public:
    		  property String^Value  { 
    																	String^ get() { 
    																					return  theValue; 																				
    																				}
    																	void set(String^ value) { 
    
    																					customPattern = 0;
    																					if (value != "")	{
    																					 //is it an integer?
    																					bool success = false;
    																					try	{
    																					int tempValue = Convert::ToInt32(value);
    																		if (tempValue > 9) tempValue = 9; if (tempValue < 0) tempValue = 0;
    																		switch (tempValue)
    																		{
    																			 case 0: customPattern = (int)ValuePattern::Zero; break;
    																			 case 1: customPattern = (int)ValuePattern::One; break;
    																			 case 2: customPattern = (int)ValuePattern::Two; break;
    																			 case 3: customPattern = (int)ValuePattern::Three; break;
    																			 case 4: customPattern = (int)ValuePattern::Four; break;
    																			 case 5: customPattern = (int)ValuePattern::Five; break;
    																			 case 6: customPattern = (int)ValuePattern::Six; break;
    																			 case 7: customPattern = (int)ValuePattern::Seven; break;
    																			 case 8: customPattern = (int)ValuePattern::Eight; break;
    																			 case 9: customPattern = (int)ValuePattern::Nine; break;
    																		}
    																		success = true;
    																	 }
    																	 catch(Exception ^e) { };
    																	 if (!success)
    																	{
    																		try {
    																		 //is it a letter?
    																			String^ tempString = Convert::ToString(value);
    																			switch (tempString->ToLower()[0]   )
    																			{
    																			case 'a': customPattern = (int)ValuePattern::A; break;
    																				 case 'b': customPattern = (int)ValuePattern::B; break;
    																			     case 'c': customPattern = (int)ValuePattern::C; break;
    																				 case 'd': customPattern = (int)ValuePattern::D; break;
    																				 case 'e': customPattern = (int)ValuePattern::E; break;
    																				 case 'f': customPattern = (int)ValuePattern::F; break;
    																				 case 'g': customPattern = (int)ValuePattern::G; break;
    																				 case 'h': customPattern = (int)ValuePattern::H; break;
    																				 case 'j': customPattern = (int)ValuePattern::J; break;
    																				 case 'l': customPattern = (int)ValuePattern::L; break;
    																				 case 'n': customPattern = (int)ValuePattern::N; break;
    																				 case 'o': customPattern = (int)ValuePattern::O; break;
    																			     case 'p': customPattern = (int)ValuePattern::P; break;
    																				 case 'q': customPattern = (int)ValuePattern::Q; break;
    																				 case 'r': customPattern = (int)ValuePattern::R; break;
    																				 case 't': customPattern = (int)ValuePattern::T; break;
    																				 case 'u': customPattern = (int)ValuePattern::U; break;
    																				 case 'y': customPattern = (int)ValuePattern::Y; break;
    																				 case '-': customPattern = (int)ValuePattern::Dash; break;
    																				 case '=': customPattern = (int)ValuePattern::Equals; break;
    																			}
    																		}
    																		catch(Exception ^e)  { }
                                                                        }
    																}
    																theValue = value; 
    																this->Invalidate();
    															}
    														}
    
    		private:
    		static int customPattern = 0;
            /// <summary>
            /// Set a custom bit pattern to be displayed on the seven segments. This is an
            /// integer value where bits 0 through 6 correspond to each respective LED
            /// segment.
            /// </summary>
    		public:
    		property int CustomPattern { 
    																	int get() { 
    																					return  customPattern; 																				
    																				}
    																	void set(int value) { 
    																					customPattern = value; 
    																					this->Invalidate();
    																	} 
    													 }
    
    		private:
    		static bool showDot = true, dotOn = false;
            /// <summary>
            /// Specifies if the decimal point LED is displayed.
            /// </summary>
    		public:
    			property  bool DecimalShow { bool get() { return showDot; } void set(bool value) { showDot = value; this->Invalidate(); } }
            /// <summary>
            /// Specifies if the decimal point LED is active.
            /// </summary>
                property bool DecimalOn { bool get() { return dotOn; } void set(bool value) { dotOn = value; this->Invalidate(); } }
    
    		private:
    			void SevenSegment_Paint(Object^ sender, PaintEventArgs^e)
    			{
                int useValue = customPattern;
    			int counter;
    
    			//MessageBox::Show("Painting");
                Brush^ brushLight = gcnew SolidBrush(colorLight);
                Brush^ brushDark  = gcnew SolidBrush(colorDark);
    
                // Define transformation for our container...
                RectangleF srcRect = RectangleF(0.0F, 0.0F, gridWidth, gridHeight);
    			RectangleF destRect = RectangleF(Padding.Left, Padding.Top, this->Width - Padding.Left - Padding.Right, this->Height - Padding.Top - Padding.Bottom);
    
                // Begin graphics container that remaps coordinates for our convenience
    			GraphicsContainer^ containerState = e->Graphics->BeginContainer(destRect, srcRect, GraphicsUnit::Pixel);
    
                Matrix^ trans = gcnew Matrix();
                trans->Shear(italicFactor, 0.0F);
                e->Graphics->Transform = trans;
    
    			e->Graphics->SmoothingMode = SmoothingMode::AntiAlias;
    			e->Graphics->PixelOffsetMode = PixelOffsetMode::Default;
    
                // Draw elements based on whether the corresponding bit is high
    
    			for(counter = 0; counter < 6; counter ++) { 
    				copiedsegPoints[counter].X = segPoints[0,counter]->X;
    				copiedsegPoints[counter].Y = segPoints[0,counter]->Y;
    			}
    
    			e->Graphics->FillPolygon( (useValue & 0x1) == 0x1 ? brushLight : brushDark, copiedsegPoints) ;
    
    			for(counter = 0; counter < 6; counter ++) { 
    				copiedsegPoints[counter].X = segPoints[1,counter]->X;
    				copiedsegPoints[counter].Y = segPoints[1,counter]->Y;
    			}
    			e->Graphics->FillPolygon((useValue & 0x2) == 0x2 ? brushLight : brushDark, copiedsegPoints);
    
    			for(counter = 0; counter < 6; counter ++) { 
    				copiedsegPoints[counter].X = segPoints[2,counter]->X;
    				copiedsegPoints[counter].Y = segPoints[2,counter]->Y;
    			}
    			e->Graphics->FillPolygon((useValue & 0x4) == 0x4 ? brushLight : brushDark, copiedsegPoints);
    
    			for(counter = 0; counter < 6; counter ++) { 
    				copiedsegPoints[counter].X = segPoints[3,counter]->X;
    				copiedsegPoints[counter].Y = segPoints[3,counter]->Y;
    			}
    			e->Graphics->FillPolygon((useValue & 0x8) == 0x8 ? brushLight : brushDark, copiedsegPoints);
    
    			for(counter = 0; counter < 6; counter ++) { 
    				copiedsegPoints[counter].X = segPoints[4,counter]->X;
    				copiedsegPoints[counter].Y = segPoints[4,counter]->Y;
    			}
    			e->Graphics->FillPolygon((useValue & 0x10) == 0x10 ? brushLight : brushDark, copiedsegPoints);
    
    			for(counter = 0; counter < 6; counter ++) { 
    				copiedsegPoints[counter].X = segPoints[5,counter]->X;
    				copiedsegPoints[counter].Y = segPoints[5,counter]->Y;
    			}
    			e->Graphics->FillPolygon((useValue & 0x20) == 0x20 ? brushLight : brushDark, copiedsegPoints);
    			for(counter = 0; counter < 6; counter ++) { 
    				copiedsegPoints[counter].X = segPoints[6,counter]->X;
    				copiedsegPoints[counter].Y = segPoints[6,counter]->Y;
    			}
    
    			e->Graphics->FillPolygon((useValue & 0x40) == 0x40 ? brushLight : brushDark, copiedsegPoints);
    
                if (showDot)
                    e->Graphics->FillEllipse(dotOn ? brushLight : brushDark, gridWidth - 1, gridHeight - elementWidth + 1, elementWidth, elementWidth);
    
                e->Graphics->EndContainer(containerState);
    
    			} // void
    
    	};
    }
    

    Während das Ganze mit C# unproblematisch ist, scheint es mit C++/cli nur irgendwie zu funktionieren. Sobald ich ein weiteres Segment mittels des Forms- Designers in ein Form hinzufüge, übernehmen die bereits hinzugefügten Elemente die Eigenschaften des zuletzt hinzugefügten Elements. Vielleicht kann mir ja hier jemand weiterhelfen.



  • Also das Ganze scheint doch irgendwie zu funktionieren – man muss aber nach jeder Werteänderung nochmal „->Update“ aufrufen, damit der Wert auch in die Klasse geschrieben wird. Andernfalls beobachtet man, dass beim Aufruf des PaintEvents jeweils nur der Wert des zuletzt bearbeiteten Control ankommt.
    So geht’s erst mal:

    void button1_Click(System::Object^  sender, System::EventArgs^  e) {
    
    				this->sevenSegment1->Value = L"5";
    				this->sevenSegment1->Update();
    
    				this->sevenSegment2->Value = L"6";
    				this->sevenSegment2->Update();
    
    	}
    

Log in to reply