Steuerelement



  • n Steuerelement isn ganz normales Fenster mit Wndproc wie sonst auch, da gibts nix besonderes zu zu sagen, Freund.



  • Jo, aber ich würde ein nnues entwickeln wollen, eins, das es noch nicht gibt.

    Ich möchte ja X Controls erzeugen und es darf ja nur eine WndProc geben.



  • SetWindowLongPtr



  • es darf ja nur eine WndProc geben.

    Lol wen du das meinst 😃

    Also du musst dann einfach bei WM_PAINT dein Ctrl zeichnen und evt. noch auf klicks usw reagieren... odg.





  • //-----------------------------------------------------------------------------
    // Defines
    
    #define WIN32_LEAN_AND_MEAN // MFC wird nicht benoetigt
    
    //-----------------------------------------------------------------------------
    // Header
    
    #include <windows.h>
    #include <TCHAR.h>
    
    //-----------------------------------------------------------------------------
    // Header
    
    HWND gMyControl;
    
    //-----------------------------------------------------------------------------
    // Event Handler
    LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
    {
    	switch(msg)
    	{
    		case WM_DESTROY:
    			PostQuitMessage(0);
    			return 0;
    
    		case WM_PAINT:
    			{
    				if(hwnd==gMyControl)
    				{
    					PAINTSTRUCT ps;
    					HDC hdc = BeginPaint(hwnd, &ps);
    
    					LineTo(hdc, 0, 0);
    					LineTo(hdc, 100, 100);
    
    					EndPaint(hwnd, &ps);
    					return 0;
    				}
    
    				break;
    			}
    
    		default: break;
    	}
    
    	return (DefWindowProc(hwnd, msg, wparam, lparam));
    }
    
    //-----------------------------------------------------------------------------
    // Main
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdline, int nCmdShow)
    {
    	WNDCLASSEX winclass;
    	winclass.cbSize = sizeof(WNDCLASSEX);
    	winclass.style = CS_VREDRAW | CS_HREDRAW | CS_OWNDC | CS_DBLCLKS;
    	winclass.lpfnWndProc = WindowProc;
    	winclass.cbClsExtra = 0; // extra class info space
    	winclass.cbWndExtra = 0; // extra window info space
    	winclass.hInstance = hInstance; // assign the application instance
    	winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    	winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    	winclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    	winclass.lpszMenuName = NULL; // the name of the menu to attach
    	winclass.lpszClassName = __T("WINCLASS1"); // the name of the class itself
    	winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    
    	RegisterClassEx(&winclass);
    	HWND hwnd;
    	hwnd = CreateWindowEx(	NULL,
    							__T("WINCLASS1"),
    							__T("Fenstertitel"),
    							WS_OVERLAPPEDWINDOW | WS_VISIBLE,
    							0,
    							0,
    							200,
    							200,
    							NULL, // handle to parent
    							NULL, // handle to menu
    							hInstance, // instance of this application
    							NULL);
    
    	if(hwnd==NULL)
    		return -10;
    
    	WNDCLASS wndcls;
        wndcls.style            = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
        wndcls.lpfnWndProc      = WindowProc;
        wndcls.cbClsExtra       = wndcls.cbWndExtra = 0;
        wndcls.hInstance        = hInstance;
        wndcls.hIcon            = NULL;
        wndcls.hCursor          = LoadCursor(NULL, IDC_ARROW);
        wndcls.hbrBackground    = (HBRUSH) (COLOR_3DFACE + 1);
        wndcls.lpszMenuName     = NULL;
        wndcls.lpszClassName    = __T("MeinSteuerelement");
    	RegisterClass(&wndcls);
    
    	gMyControl = CreateWindowEx(NULL,__T("MeinSteuerelement"), __T("Meine Komponente"), WS_CHILD |
    	WS_VISIBLE, 20, 20, 100, 20, hwnd, NULL, hInstance,
    	NULL);
    
    	if( gMyControl==0)
    		return -1;
    
    	MSG msg;
    	while(GetMessage(&msg, NULL, 0, 0))
    	{
    		// translate any accelerator keys
    		TranslateMessage(&msg);
    		// send the message to the window proc
    		DispatchMessage(&msg);
    	}
    	return 0;
    }
    


  • thx, sowas suchte ich!!!!

    Ich brauche keine Romane, sondern nur ein kleines Sample.



  • Problem ist noch bei der ganzen Sache, dass das Control über die normale WndProc vom Fenster läuft. Aber wenn ich nun 100 Controls erzeugen würde, kann ich doch nicht immer wieder mit if frage, welche Fensterhandle grade bearbeitet wird. Gibt es da nicht noch eine bessere Lösung?



  • ein steuerlement sollte seine eigene wndproc haben und die sich ned mit dem programm teilen mit globalen variablen, dasist doch frickelei wenn ich je welche gesehen habe



  • Jop, genau das meine ioch, aber wie kann ich x elemente über eine ControlProc laufen lassen??? ICh habe ja keine globalen Variablen...

    case WM_PAINT:
                {
                    if(hwnd==gMyControl)
                    {
                        PAINTSTRUCT ps;
                        HDC hdc = BeginPaint(hwnd, &ps);
    
                        LineTo(hdc, 0, 0);
                        LineTo(hdc, 100, 100);
    
                        EndPaint(hwnd, &ps);
                        return 0;
                    }
    

    --> Ist mir zu statisch.



  • na registier halt eine eigene wndclass mit einer eigenen wndproc für dein steuerelement und benutz diese wndclass dann beim aufruf von CreateWindow wenn du ein steuerelement anlegen willst. die steuer element spezifischen daten kannst du per SetWindowLong/GetWindowLong mit GWL_USERDATA in die jeweilige Instanz des Steuerelements integrieren.



  • Wär eine Idee und wie hat es überhaupt MS mit den Controls(Buttons, Edits....) gemacht?



  • Subclassing !?
    Wenn Du VS hast, kannst Du doch in den Source reinschauen...



  • Ich glaube nicht das er MFC meint.



  • ............ schrieb:

    Ich glaube nicht das er MFC meint.

    Ahhh... sorry....
    Windows hat es genau so gemacht... jedes Control hat eine eigene WndClass:
    (falls Du schon mal die Doku zu CreateWindow gelesen hast, wäre Dir das aufgefallen):
    http://msdn.microsoft.com/library/en-us/winui/winui/windowsuserinterface/windowing/windows/windowreference/windowfunctions/createwindow.asp



  • Wenn du keine static Variablen nimmst, sondern SetWindowLongPtr/GetWindowLongPtr um Daten mit einem Fenster zu assoziieren und wieder abzurufen, gibt es überhaupt kein Problem.



  • Gibt es dazu ein Sample??? Ich habe sowas noch nie gemacht



  • ich Empfehle dir Folgendes:

    Erstelle eine Klasse Fenster - diese beistitzt einen Behälter (z. B. stl vector) für Komponenten. Komponenten sind z. B. Buttons, Label und Textboxen

    verpasse deiner Fenterklasse eine add Methode, so dass folgendes Möglich ist:

    MyWindow.Add(new Label("Mein Label"));

    Jede Komponente schickt beim Auftretten eines Event eine ActionEvent Objekt an einen ActionListener - ein ActionListener ist z. B. dein Fenster - jeder ActionListener muss die Methode actionPerformed(ActionEvent e) implementieren
    Ein ActionEvent entählt die Methode getCallbackString() - diese liefert einen stl String - diesen CallbackString kannst du vorher zuweisen:

    Die bei Nvidia machen das genau so wie ich meine:
    http://download.nvidia.com/developer/Third_Party/Nature/NatureScene.zip

    wollte das ganze mal so umprogrammieren, dass es einfach möglich ist "normale" Buttons, Textboxen und Labels mit Events zu versehen - soll ähnlich wie in Java funktionieren



  • aus dem Nivida Nature Demo:

    void SceneFrame::actionPerformed(GUIEvent &evt)
    {
      const String &callbackString  = evt.getCallbackString();
      GUIRectangle *sourceRectangle = evt.getEventSource();
      int           widgetType      = sourceRectangle->getWidgetType();
    
      if(widgetType == CHECK_BOX)
      {
        GUICheckBox   *checkBox = (GUICheckBox*)sourceRectangle;
        if(checkBox->isClicked())
        {
          if(callbackString == "aToCoverage") terrain.setAlphaToCoverageFlag(checkBox->isChecked());
          if(callbackString == "eOcclusion")  terrain.setOcclusionCullingFlag(checkBox->isChecked());
          if(callbackString == "eFrustum")    terrain.setFrustumCullingFlag(checkBox->isChecked());
          if(callbackString == "rGrass")      terrain.setDrawGrassFlag(checkBox->isChecked());
          if(callbackString == "rWater")      renderWater = checkBox->isChecked();
          if(callbackString == "rAABB")       terrain.setRenderAABBFlag(checkBox->isChecked());
          if(callbackString == "rMode")       terrain.setWireFrameFlag(checkBox->isChecked());
          if(callbackString == "rTBN")        terrain.setDrawTBNFlag(checkBox->isChecked());
        }
      }
    
      if(widgetType == SLIDER)
      {
        GUISlider   *slider = (GUISlider*)sourceRectangle;
    
        if(callbackString == "aReference")
        {
          terrain.setAlphaReference(slider->getProgress());
          slider->setLabelString(String("Alpha Reference: ") + slider->getProgress());
        }
    
        if(callbackString == "aBooster")
        {
          terrain.setAlphaBooster((slider->getProgress()*2.0f));
          slider->setLabelString(String("Alpha Booster: ") + terrain.getAlphaBooster()); 
        }
    
        if(callbackString == "red")
        {
          skyInfo.x = slider->getProgress();
          slider->setLabelString(String("Red Intensity: ") + skyInfo.x); 
        }
    
        if(callbackString == "blue")
        {
          skyInfo.z = slider->getProgress();
          slider->setLabelString(String("Blue Intensity: ") + skyInfo.z); 
        }
    
        if(callbackString == "green")
        {
          skyInfo.y = slider->getProgress();
          slider->setLabelString(String("Green Intensity: ") + skyInfo.y); 
        }
    
        if(callbackString == "sSpeed")
        {
          skyInfo.w = slider->getProgress()*2.0f;
          slider->setLabelString(String("Scrolling Speed: ") + slider->getProgress()); 
        }
      }
    }
    


  • hab ein wenig rumüberlegt und jetzt folgendes "Pseudo"-Framework *g* gebastelt:

    namespace GUI
    {
    	class Position;
    
    	class Component
    	{
    	public:
    		virtual void  setCallbackString(const string& callback) = 0;
    		virtual void  setCallbackString(const char*   callback) = 0;
    		virtual const string & getCallbackString() = 0;
    		virtual void  setPosition(Position &pos);
    		virtual Postion &void getPosition();
    		virtual void  setWidth(int width);
    		virtual void  setHeight(int height);
    	};
    
    	class Button : Component
    	{
    	public:
    		string& getText();
    		void setText(string Text);
    	};
    
    	class TextBox : Component
    	{
    	public:
    		string& getText();
    		void setText(string Text);
    	};
    
    	class Label : Component
    	{
    	public:
    		Label(string Text);
    		string& getText();
    		void setText(string Text);
    	};
    
    	class Canvas : Component
    	{
    		DrawLine(Postion a, Positon b);
    	}
    
    	class ActionEvent
    	{
    	public:
    		enum Type = {Button, TextBox, Label};
    
    	private:
    		Type		m_type; // von welchem Typ wurde Event ausgeloest
    		Component	source; // Quelle des Events
    
    	public:
    		Type	  getType();
    		Component getEventSource();
    	};
    
    	class Window
    	{
    		vector<Component> ComponentContainer;
    
    	public:
    		void add(Component component);
    
    		void setActionListener(ActionListener *listener);
    	};
    
    	class ActionListener
    	{
    		virtual void actionPerformed(ActionEvent &evt);
    	};
    
    	class WindowsManager
    	{
    	  public:
    		static bool  addWindow    (Window *windowPTR);
    
    		static bool  removeWindow (Window *windowPTR);
    
    		static LRESULT CALLBACK windowEventsProcessor(HWND   hWnd  , UINT   wMsg,
    													  WPARAM wParam, LPARAM lParam);
    	  private:
    		static vector<Window*>  windowsList; 
    	};
    
    }
    
    class MyApp : Window, ActionListener
    {
    	class MyApp
    	{
    		m_Label = new Label("Mein Label");
    		m_Button = new Button("Mein Button");
    		m_Button.setCallbackString("Mein Button");
    	}
    
    	virtual void actionPerformed(GUI::ActionEvent &evt)
    	{
    		if(evt.getType() == GUI::ActionEvent::Type.Button)
    		{
    			if(m_Button.getCallbackString() == "Mein Button")
    			{
    				MeinButton_Click();
    			}
    		}
    	}
    
    	void MeinButton_Click()
    	{
    		// was soll getan werden wenn auf Mein Button
    		// geklickt wird?
    	}
    
    	GUI::Label	m_Label;
    	GUI::Button m_Button;
    }
    
    int main()
    {
    	MyApp App = new MyApp();
    }
    

    muss nur noch die Klassen implementieren (dauert ca. 1. Woche - da wenig Erfahrung mit WinAPI - muss mich erst einarbeiten) dann läufts... hab aber leider keine Zeit dafür


Anmelden zum Antworten