Steuerelement



  • 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



  • Ideologisch motiviertes Bastelwerk.



  • Warum nimmst Du nicht die MFC? (oder sonstige Wrapper um die WinAPI?)



  • Ideologisch motiviertes Bastelwerk.

    *lol*



  • Ich habe noch ein kleines Problem... mir will einfach keine Lösung einfallsen...
    Wie kann ich prüfen, ob der Cursor über dem Control ist, damit das Control seine Farbe änder?

    LRESULT CALLBACK CtrlProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
    	static RECT rect = {0, 0, 0, 0};
    	static PAINTSTRUCT ps;
    	static  HDC hDC;
    	HBRUSH hBr = CreateSolidBrush(RGB(255, 155, 0));;
    
    	switch(uMsg)
    	{
    	case WM_CREATE:
    		hDC = GetDC(hWnd);
    		GetClientRect(hWnd, &rect);
    		return 0;
    
    	case WM_PAINT:
    		{
    			SelectObject(hDC, hBr);
    			RoundRect(hDC, rect.left, rect.top, rect.right, rect.bottom, 10, 10);
    			ValidateRect(hWnd, NULL);
    			return 0;
    		}
    
    	case WM_SIZE:
    		rect.right	= LOWORD (lParam);
    		rect.bottom = HIWORD (lParam);
    		return 0;
    
    	case WM_DESTROY:
    		ReleaseDC(hWnd, hDC);
    		return 0;
    
    	default:
    		break;
    	}
    
    	return(DefWindowProc(hWnd, uMsg, wParam, lParam));
    }
    


  • MOUSE OVER EVENT



  • WM_MOUSEMOVE



  • ???

    nee, mit WM_MOUSEMOVE bin ich da nicht viel weiter gekommen.



  • Was ging nicht? Du brauchst natürlich auch noch TrackMouseEvent...

    Aber schau doch einfach in die MFC... da ist schon alles gemacht und da kannst Du Dir es ganz simpel abschauen!



  • in welchen MFC header soll ich gucken?



  • Ich dachte Du hast VS6 oder später... sorry...
    Macht aber auch nix: Dann schau einfach in der WTL:
    http://sourceforge.net/projects/wtl/

    Oder in sonstigen Win32-API Wrappern:
    http://smartwin.sourceforge.net/



  • LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
    	switch(uMsg)
    	{
    	case WM_CREATE:
    		return 0;
    
    	case WM_DESTROY:
     		PostQuitMessage(0);
    		return 0;
    
    	default:
    		break;
    	}
    
    	return(DefWindowProc(hWnd, uMsg, wParam, lParam));
    }
    
    LRESULT CALLBACK CtrlProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
    	static RECT rect = {0, 0, 0, 0};
    	static PAINTSTRUCT ps;
    	static  HDC hDC;
    	HBRUSH hBr = CreateSolidBrush(RGB(255, 155, 0));
    
    	switch(uMsg)
    	{
    	case WM_CREATE:
    		GetClientRect(hWnd, &rect);
    		hDC = GetDC(hWnd);
    
    		TRACKMOUSEEVENT track;
    		track.cbSize		= sizeof(track);
    		track.hwndTrack		= hWnd;
    		track.dwFlags		= TME_HOVER | TME_LEAVE;
    		track.dwHoverTime	= 500;
    
    		_TrackMouseEvent(&track);
    
    		return 0;
    
    	case WM_PAINT:
    		{
    			SelectObject(hDC, hBr);
    			RoundRect(hDC, rect.left, rect.top, rect.right, rect.bottom, 10, 10);
    			ValidateRect(hWnd, NULL);
    			return 0;
    		}
    
    	case WM_MOUSEHOVER: 
    		hBr = CreateSolidBrush(RGB(0, 55, 200));
                    InvalidateRect(hWnd, NULL, TRUE);
    		return 0;
    
    	case WM_MOUSELEAVE: 
    		hBr = CreateSolidBrush(RGB(255, 155, 0));
                    InvalidateRect(hWnd, NULL, TRUE);
    		return 0;
    
    	case WM_SIZE:
    		rect.right	= LOWORD (lParam);
    		rect.bottom = HIWORD (lParam);
    		return 0;
    
    	case WM_DESTROY:
    		ReleaseDC(hWnd, hDC);
    		return 0;
    
    	default:
    		break;
    	}
    
    	return(DefWindowProc(hWnd, uMsg, wParam, lParam));
    }
    

    Funktioniert aber leider nicht...



  • Hat keiner eine Idee, woran es liegt?



  • hBr ist nicht static der wird doch jedes mal wieder mit CreateSolidBrush(RGB(255, 155, 0)) belegt. hBr sollte ausserdem dann echt ans hWnd geknüpft sein wenn es static ist hast du ein prob wenn du mehr als 1 steuerelement machst 😮

    ausserdem solltest du den brush auch wieder mit DeleteObject zerstören


Anmelden zum Antworten