Anwendungsdesign



  • Hallo!

    Ich bin gerade dabei für unsere Firma ein Tool zu programmieren. Es geht hierbei um eine Software in dem ein Szenegraph visualisiert werden soll. Die 3D Visualisierung ist nicht das Problem, die Abarbeitung auch nicht. Ich habe zwar schon genug 3D Sachen programmiert, mit GUI Programmierung unter der WinAPI (damit will ich es ja realisieren) leider kaum Erfahrung.

    Ich stelle am besten mal meine Idee der Oberfläche vor:

    *******************************
    *menü**************************
    *******************************
    *      *                      *
    * GUI  *                      *
    * Ele  *                      *
    * men  *                      *
    * te   *                      *
    *      *                      *
    *      *          3D          *
    *      *                      *
    *      *                      *
    *      *                      *
    *      *                      *
    *      *                      *
    *      *                      *
    *      *                      *
    *      *                      *
    *******************************
    

    Im Feld 3D sollen hierbei die 3D Daten visualisiert werden. Das ganze wird in eine DLL ausgelagert, die dort in den entsprechenden DC rendern soll.

    Die GUI - Elemente beschränken sich eigentlich auf N Slider, und M Checkboxen

    Das Fenster soll entweder minimiert oder maximiert sein.

    Wie gehe ich jetzt am besten ran, die Slider und Checkboxen zu verteilen? Die Anzahl, Benennungen und Wertebereiche sind mir ja erst zur Laufzeit bekannt.

    Des weiteren stellt sich mir die Frage wie ich das 3D Window lösen soll,... (OpenGL) dafür brauche ich ja fast ein zweites, festes Child Window, oder?

    Soll ich dann die GUI - Elemente auch so platzieren (zweites Child)?

    Wie designed man am besten eine entsprechende Nachrichtenabarbeitung, die an den Core der Applikation gehen soll?

    Könnt Ihr mir gute Tutorials, etc empfehlen? Den Petzold hab ich zwar hier, aber Ihr seht vielleicht: Ich brauch eher einen Rat über die Herangehensweise...

    Vielen Dank,

    Vibe



  • vibe schrieb:

    Wie gehe ich jetzt am besten ran, die Slider und Checkboxen zu verteilen? Die Anzahl, Benennungen und Wertebereiche sind mir ja erst zur Laufzeit bekannt.

    wenn du einen graphen rendern möchtest könntest du doch ne treeview
    dafür verwenden, fande ich sinnvoller und zb einen dbclick auf das node abfangen ein property dialog öffnen und somit alles einstellen.
    werte wie anzahl, label, wertebereiche kannst du auch zur laufzeit einstellen.
    sehe blos ein problem mit n, was passiert wenn du einen scenenode veränderen
    möchtest und n+1 eigenschaften hast?

    vibe schrieb:

    Des weiteren stellt sich mir die Frage wie ich das 3D Window lösen soll,... (OpenGL) dafür brauche ich ja fast ein zweites, festes Child Window, oder?

    jep, ich habe bei meinem editor es so gelösst das zoomen, pannen, etc in
    der gl fenster schleife abgefangen werden und commandos ans main geschickt werden.

    vibe schrieb:

    Soll ich dann die GUI - Elemente auch so platzieren (zweites Child)?

    würde ich nicht machen. zuviel schreiarbeit, noch ne nachrichtenschleife, ...

    vibe schrieb:

    Wie designed man am besten eine entsprechende Nachrichtenabarbeitung, die an den Core der Applikation gehen soll?

    siehe oben

    vibe schrieb:

    Könnt Ihr mir gute Tutorials, etc empfehlen? Den Petzold hab ich zwar hier, aber Ihr seht vielleicht: Ich brauch eher einen Rat über die Herangehensweise...

    ich könnte dir mal heut nacht ein altes, kleines framework, vorraussetzung ich finde es noch, schicken oder hierher posten.



  • miller_m schrieb:

    wenn du einen graphen rendern möchtest könntest du doch ne treeviewdafür verwenden, fande ich sinnvoller und zb einen dbclick auf das node abfangen ein property dialog öffnen und somit alles einstellen.
    werte wie anzahl, label, wertebereiche kannst du auch zur laufzeit einstellen.
    sehe blos ein problem mit n, was passiert wenn du einen scenenode veränderen
    möchtest und n+1 eigenschaften hast?

    Ja, das wäre natürlich der bessere Weg. Es handelt sich hierbei jedoch um eine bereits stark vereinfacht Form eines Szenegraphen, der einzig und allein schaltbare Evaluators und animierbare DOFs enthält. Es ist ein Converter, der von verschiedenen Files (Maya Obj, Multigen-Paradigm OpenFlight, etc) in ein internes Format wandelt, das ich im speziellen in meiner Engine einsetze. Deswegen denke ich ist eine Liste mit den Evaluators die man zum Test ein- und ausschalten kann, sowie die Slider für die animated DOFs doch übersichtlicher, oder?

    miller_m schrieb:

    jep, ich habe bei meinem editor es so gelösst das zoomen, pannen, etc in
    der gl fenster schleife abgefangen werden und commandos ans main geschickt werden.

    ah, okay. D.h. ich erzeuge ein Child - Window das ich extern implementiere und dann statisch in meiner Applikation platziere?

    miller_m schrieb:

    würde ich nicht machen. zuviel schreiarbeit, noch ne nachrichtenschleife, ...

    Okay, klingt sinnvoll. Dachte mir nur ich mach das im Windows - Forms style... aber stimmt eigentlich. Die Elemente platziere ich einfach in dem Bereich nach entsprechenden Regeln und gut is...

    vibe schrieb:

    Wie designed man am besten eine entsprechende Nachrichtenabarbeitung, die an den Core der Applikation gehen soll?

    siehe oben

    miller_m schrieb:

    ich könnte dir mal heut nacht ein altes, kleines framework, vorraussetzung ich finde es noch, schicken oder hierher posten.

    Das wär natürlich sehr cool 🙂 Kann man hier Files anhängen oder direkt hochladen? Alternativ natürlich gerne per EMail, eventuell wäre es aber für mehrere interessant (vorausgesetzt das ist in deinem Interesse). Ich könnte es auch auf meinen Server laden...

    TIA,

    vibe



  • vibe schrieb:

    Ja, das wäre natürlich der bessere Weg. Es handelt sich hierbei jedoch um eine bereits stark vereinfacht Form eines Szenegraphen, der einzig und allein schaltbare Evaluators und animierbare DOFs enthält. Es ist ein Converter, der von verschiedenen Files (Maya Obj, Multigen-Paradigm OpenFlight, etc) in ein internes Format wandelt, das ich im speziellen in meiner Engine einsetze. Deswegen denke ich ist eine Liste mit den Evaluators die man zum Test ein- und ausschalten kann, sowie die Slider für die animated DOFs doch übersichtlicher, oder?

    und was hälst du davo:
    du hast nur einen slider und eine box hast und nach einem klick
    auf das symbol im deinem renderfenster, vielleicht etwas unglücklich ausgedrückt aber ich denke du wirst die transformation mit irgendeinem symbol sichtbar machen wollen, wird das ensprechende element aktiviert und die werte übernommen.

    vibe schrieb:

    ah, okay. D.h. ich erzeuge ein Child - Window das ich extern implementiere und dann statisch in meiner Applikation platziere?

    verstehe ich nicht so ganz 🙄

    vibe schrieb:

    Das wär natürlich sehr cool 🙂 Kann man hier Files anhängen oder direkt hochladen? Alternativ natürlich gerne per EMail, eventuell wäre es aber für mehrere interessant (vorausgesetzt das ist in deinem Interesse). Ich könnte es auch auf meinen Server laden...

    ist nicht viel, um genau zu sein eine portierung von http://www.gamedev.net/reference/articles/article1358.asp
    in winapi, ich werd es einfach mal hierher kopieren



  • miller_m schrieb:

    vibe schrieb:

    ah, okay. D.h. ich erzeuge ein Child - Window das ich extern implementiere und dann statisch in meiner Applikation platziere?

    verstehe ich nicht so ganz 🙄

    Hehe, okay. Meine Vorstellung: Das OpenGL Rendering mache ich in ein normales Fenster, welches ich jedoch als Child - Window in das Application Window platziere, oder?

    Ich brauch dafür ja einen extra Device Context... Sonst würde ich ja meine Controls überzeichnen. Oder sehe ich das Falsch?



  • vibe schrieb:

    Hehe, okay. Meine Vorstellung: Das OpenGL Rendering mache ich in ein normales Fenster, welches ich jedoch als Child - Window in das Application Window platziere, oder?

    jep

    vibe schrieb:

    Ich brauch dafür ja einen extra Device Context... Sonst würde ich ja meine Controls überzeichnen. Oder sehe ich das Falsch?

    ich vermute mal du siehst was falsch. den das childwnd(opengl) hat gar nix
    mit deinen ctrls zu tun.



  • miller_m schrieb:

    vibe schrieb:

    Hehe, okay. Meine Vorstellung: Das OpenGL Rendering mache ich in ein normales Fenster, welches ich jedoch als Child - Window in das Application Window platziere, oder?

    jep

    vibe schrieb:

    Ich brauch dafür ja einen extra Device Context... Sonst würde ich ja meine Controls überzeichnen. Oder sehe ich das Falsch?

    ich vermute mal du siehst was falsch. den das childwnd(opengl) hat gar nix
    mit deinen ctrls zu tun.

    Ja, den vom Childwindow. Wenn ich den DC vom AppWnd nehme, würde ich ja entsprechende Dinge überzeichnen...

    So langsam kommt mir die Idee 🙂



  • hat länger gedauert als gedacht 😃
    den source nicht so ernst nehmen es ging da nur ein "grobes" design, er ist auch
    schon ziemlich als (März 04) und wird mit sicherheit einige fehler beinhalten
    dich ich heute nicht mehr mache, aber das wirst du ja selber kennen.
    es handelt sich hierbei nur um das (minimalste) framework, mit nur einen viewport, aber falls du noch fragen hast du weisst wie es geht. 😃

    #if(WINVER <= 0x0500)
    	#define WINVER 0x0500
    #endif
    
    #if(_WIN32_IE <= 0x0500)
        #define _WIN32_IE 0x0500  // IE 5.0
    #endif
    
    #include <windows.h>
    #include <commctrl.h>
    #include <gl/gl.h>
    
    #include "resource.h"
    
    // D E F I N E S
    #define SZWNDCLASS	TEXT("FrameworkEditor")	// fensterklasse
    #define SZGLCLASS	TEXT("OpenGLWnd")		// klasse gl fenster
    #define SZWNDTITLE	TEXT("Framework")       // fenstername
    
    // F U N K T I O N E N
    LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
    LRESULT CALLBACK GLWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
    BOOL GLWindowCreate(HWND hwndParent);		// opengl fenster erstellen
    void InitEditor(HWND hwndParent);			// editor mit standardwerten initialisieren
    void Update(HWND hwndParent);				// rendern
    
    // G L O B A L E   V A R I A B E L E N
    BOOL        	g_bDone         = FALSE;	// mainloop
    BOOL            g_bAppActive    = TRUE;     // application aktiv
    HDC				g_hDC			= NULL;		// GDI device context
    HGLRC	    	g_hGLrc         = NULL;		// handle rendering context
    
    int WINAPI WinMain(
        HINSTANCE hThisInstance,
        HINSTANCE hPrevInstance,
        LPSTR lpszArgument,
        int nCmdShow)
    {
        // überprüfen ob programm schon gestartet ist
    	CreateMutex(NULL, TRUE, "Framework Started");
    	if(GetLastError() == ERROR_ALREADY_EXISTS)
    	{
    		HWND        hWndFirst;
    		hWndFirst = FindWindow(SZWNDCLASS, NULL);
    
    		BringWindowToTop(hWndFirst);
    		SetForegroundWindow(hWndFirst);
    
    		return -1;
    	}
    
        // argumente benutzt das framework nicht
        UNREFERENCED_PARAMETER(lpszArgument);
    
    	InitCommonControls();
    
        HWND 		hwnd;
        MSG 		msg;
        WNDCLASSEX 	wincl;
    
        wincl.hInstance     = hThisInstance;
        wincl.lpszClassName = SZWNDCLASS;
        wincl.lpfnWndProc   = WindowProc;
        wincl.style         = CS_HREDRAW | CS_VREDRAW;
        wincl.cbSize        = sizeof(WNDCLASSEX);
        wincl.hIcon         = LoadIcon(hThisInstance, MAKEINTRESOURCE(IDI_MAIN));
        wincl.hIconSm       = LoadIcon(hThisInstance, MAKEINTRESOURCE(IDI_MAIN));
        wincl.hCursor       = LoadCursor(NULL, IDC_ARROW);
        wincl.lpszMenuName  = "MAINMENU";
        wincl.cbClsExtra    = 0;
        wincl.cbWndExtra    = 0;
        wincl.hbrBackground = (HBRUSH)(COLOR_WINDOW);
    
        if(!RegisterClassEx(&wincl))
            return -1;
    
        wincl.hInstance     = hThisInstance;
        wincl.lpszClassName = SZGLCLASS;
        wincl.lpfnWndProc   = GLWindowProc;
        wincl.style         = CS_HREDRAW | CS_VREDRAW;
        wincl.cbSize        = sizeof(WNDCLASSEX);
        wincl.hIcon         = NULL;
        wincl.hIconSm       = NULL;
        wincl.hCursor       = LoadCursor(NULL, IDC_CROSS);
        wincl.lpszMenuName  = NULL;
        wincl.cbClsExtra    = 0;
        wincl.cbWndExtra    = 0;
        wincl.hbrBackground = (HBRUSH)(COLOR_WINDOW);
    
        if(!RegisterClassEx(&wincl))
            return -1;
    
        if(!(hwnd = CreateWindowEx(
    			WS_EX_APPWINDOW,
    			SZWNDCLASS,
    			SZWNDTITLE,
    			WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN |WS_VISIBLE,
    			25,
    			25,
    			GetSystemMetrics(SM_CXSCREEN) - 50,
    			GetSystemMetrics(SM_CYSCREEN) - 100,
    			HWND_DESKTOP,
    			NULL,
    			hThisInstance,
                NULL)))
    	{
    		MessageBox(
    			NULL,
    			"Couldn't create Mainwindow",
    			"Error",
    			MB_OK | MB_ICONEXCLAMATION);
    		return -1;
    	}
    
        ShowWindow(hwnd, nCmdShow);
    
        while(!g_bDone)
        {
            if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    		{
    			TranslateMessage(&msg);
    			DispatchMessage(&msg);
    		}
    		else
    		{
    			if(g_bAppActive)
    			{
    				Update(hwnd);
    				SwapBuffers(g_hDC);
    			}
    		}
        }
    
        // aufräumen
    	if(g_hGLrc)
    	{
    		wglMakeCurrent(NULL, NULL);
    		wglDeleteContext(g_hGLrc);
    	}
    
    	ReleaseDC(hwnd, g_hDC);
    	DestroyWindow(hwnd);
    	UnregisterClass(SZWNDCLASS, hThisInstance);
    
        return msg.wParam;
    }
    
    LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    	static HWND		hwndTabCtrl;
    
    	switch(msg)
    	{
    		case WM_CREATE:
    			{
    				// opengl fenster erstellen
    				if(!GLWindowCreate(hwnd))
    					DestroyWindow(hwnd);
    
    				// als beispiel habe ich ein tab control hinzugefügt
    				if(!(hwndTabCtrl = CreateWindowEx(
    						0,
    						WC_TABCONTROL,
    						TEXT(""),
    						WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_CLIPSIBLINGS |
    						TCS_FOCUSNEVER | TCS_SINGLELINE,
    						0, 0, 0, 0,
    						hwnd,
    						(HMENU)IDC_TAB,
    						((LPCREATESTRUCT)lParam)->hInstance,
    						NULL)))
    				{
    					MessageBox(
    						hwnd,
    						"Couldn't create Tabcontrol",
    						"Error",
    						MB_OK | MB_ICONEXCLAMATION);
    					DestroyWindow(hwnd);
    				}
    
    				TCITEM  item;
    
    				item.pszText = TEXT("Edit1");
    				TabCtrl_InsertItem(hwndTabCtrl, 0, &item);
    
    				item.pszText = TEXT("Edit2");
    				TabCtrl_InsertItem(hwndTabCtrl, 1, &item);
    
    			    InitEditor(hwnd);
    			}
    			break;
    		case WM_ACTIVATEAPP:
    				g_bAppActive = (BOOL)wParam;
    			break;
    		case WM_COMMAND:
    			switch(LOWORD(wParam))
    			{
    				// file --------------------------------------------------------
    				case IDM_EXIT:
    						PostMessage(hwnd, WM_CLOSE, 0, 0);
    					break;
    				// help --------------------------------------------------------
    				case IDM_\1:
    					MessageBox(
    							hwnd,
    							"Opengl Leveleditor Framework",
    							"About",
    							MB_OK);
    					break;
    			}
    			break;
    		case WM_NOTIFY:
    			// tab click abfangen
    			break;
    		case WM_SIZE:
    				if(wParam != SIZE_MINIMIZED)
    				{
    					RECT	rc;
    					GetClientRect(hwnd, &rc);
    
    					int nGlWndWidth = rc.right - rc.left - 155;
    					int nGlWndHeight = rc.bottom - rc.top;
    
    					MoveWindow(
    						hwndTabCtrl,
    						0, 0, 150, nGlWndHeight, TRUE);
    
    					MoveWindow(
    						GetDlgItem(hwnd, IDC_GLWND),
    						155, 0, nGlWndWidth, nGlWndHeight, TRUE);
    				}
    			break;
    		case WM_GETMINMAXINFO:
    				((MINMAXINFO*)lParam)->ptMinTrackSize.x = 800;
    				((MINMAXINFO*)lParam)->ptMinTrackSize.y = 600;
    			break;
    		case WM_CLOSE:
    				DestroyWindow(hwnd);
    			break;
            case WM_DESTROY:
    	            PostQuitMessage(0);
                    g_bDone = TRUE;
                break;
            default:
                return DefWindowProc(hwnd, msg, wParam, lParam);
        }
    
        return 0;
    }
    
    LRESULT CALLBACK GLWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch(msg)
        {
            case WM_MOUSEMOVE:
    				// tasten abfangen zb: strg, shift
    				// diff ausrechenen vom mauspunkt dann
    				// --> zoomen, panen, rotieren, etc
                break;
    		case WM_CLOSE:
    				DestroyWindow(hwnd);
    			break;
            case WM_DESTROY:
    	            PostQuitMessage(0);
                break;
            default:
                return DefWindowProc(hwnd, msg, wParam, lParam);
        }
        return 0;
    }
    
    BOOL GLWindowCreate(HWND hwndParent)
    {
    	HWND	hwnd;
        int     nPixelformat;
    
        if(!(hwnd = CreateWindowEx(
                WS_EX_CLIENTEDGE,
                SZGLCLASS,
                "",
                WS_CHILD | WS_VISIBLE,
                0, 0, 0, 0,
                hwndParent,
                (HMENU)IDC_GLWND,
                (HINSTANCE)GetWindowLong(hwndParent, GWL_HINSTANCE),
                NULL)))
            return FALSE;
    
    	if(!(g_hDC = GetDC(hwnd)))
    	{
            MessageBox(
            	hwndParent,
    			"Can't create a GL Device Context.",
    			"Error",
    			MB_OK | MB_ICONEXCLAMATION);
    		return FALSE;
        }
    
    	PIXELFORMATDESCRIPTOR pfd =
    	{
    		sizeof(PIXELFORMATDESCRIPTOR),
    		1,
    		PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
    		PFD_TYPE_RGBA,
    		16,
    		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    		16,
    		0, 0,
    		PFD_MAIN_PLANE,
    		0, 0, 0, 0
    	};
    
    	if(!(nPixelformat = ChoosePixelFormat(g_hDC, &pfd)))
    	{
            MessageBox(
            	hwndParent,
    			"Can't find a suitable PixelFormat",
    			"Error",
    			MB_OK | MB_ICONEXCLAMATION);
    		return FALSE;
    	}
    
    	if(!SetPixelFormat(g_hDC, nPixelformat, &pfd))
    	{
            MessageBox(
            	hwndParent,
    			"Can't set the PixelFormat",
    			"Error",
    			MB_OK | MB_ICONEXCLAMATION);
    		return FALSE;
    	}
    
    	if(!(g_hGLrc = wglCreateContext(g_hDC)))
    	{
            MessageBox(
            	hwndParent,
    			"Can't create a GL Rendering Context",
    			"Error",
    			MB_OK | MB_ICONEXCLAMATION);
    		return FALSE;
    	}
    
    	if(!wglMakeCurrent(g_hDC, g_hGLrc))
    	{
            MessageBox(
            	hwndParent,
    			"Can't activate the GL Rendering Context",
    			"Error",
    			MB_OK | MB_ICONEXCLAMATION);
    		return FALSE;
    	}
    
        return TRUE;
    }
    
    void InitEditor(HWND hwndParent)
    {
    	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    	glClearDepth(1.0f);
    	// gl init ...
    }
    
    void Update(HWND hwndParent)
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    }
    

Anmelden zum Antworten