Probleme mit 2 OpenGL-Fenstern
-
Als erstens musst du für beide Fenster nen eigenen Pixeldesxriptor machen. Am besten irgenwo ne init-Methode die du dann aufrufst für jedes Fenster.(wenn das dein OpenGLCreate darstellen soll, dann muss es in beide Tabklassen)
Ansonsten schreibt du einfach vor deinem ersten fensterspezifischen OpenGL-Befehl
wglMakeCurrent(hDC,hRC);Den Device- und Rendercontext legst du ja in der init-Methode an für jedes Fenster(werden also Membervariable der Klasse sein).
Das wars eigentlich schon.
Für das OpenGL-Zeugs empfiehlt es sich, ne eigene KLasse zu schreiben, welche du dann in allen Fenstern benutzt.
-
Hmmmm... kannst Du etwas spezifischer werden? Hier mal etwas Code:
Aus meiner Tab1-Klasse:
BOOL tabDialog2::OnInitDialog() { // Get size and position of the template textfield we created before in the dialog editor GetDlgItem(IDC_OPENGL)->GetWindowRect(rect_opengl); // Convert screen coordinates to client coordinates ScreenToClient(rect_opengl); // Create OpenGL Control window m_oglGraph->oglCreate(rect_opengl, this); // return 0 if everything went fine return 0; }Aus der OpenGLCtrl Klasse:
int COpenGLCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CWnd::OnCreate(lpCreateStruct) == -1) return -1; oglInitialize(); return 0; } void COpenGLCtrl::oglCreate(CRect rect, CWnd *parent) { CString className = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW | CS_OWNDC, NULL, (HBRUSH)GetStockObject(BLACK_BRUSH), NULL); CreateEx(0, className, "OpenGL", WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS, rect, parent, 0); // Set initial variables' values m_oldWindow = rect; m_originalRect = rect; hWnd = parent; } void COpenGLCtrl::OnPaint() { CPaintDC dc(this); // device context for painting ValidateRect(NULL); } void COpenGLCtrl::oglInitialize(void) { // Initial Setup: // static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, 32, // bit depth 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, // z-buffer depth 0, 0, 0, 0, 0, 0, 0, }; // Get device context only once. hdc = GetDC()->m_hDC; // Pixel format. m_nPixelFormat = ChoosePixelFormat(hdc, &pfd); SetPixelFormat(hdc, m_nPixelFormat, &pfd); // Create the OpenGL Rendering Context. hrc = wglCreateContext(hdc); wglMakeCurrent(hdc, hrc); // Basic Setup: // // Set color to use when clearing the background. glClearColor(0.6f, 0.6f, 0.6f, 1.0f); glClearDepth(1.0f); // Turn on backface culling glFrontFace(GL_CCW); glCullFace(GL_BACK); // Turn on depth testing glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); // Send draw request OnDraw(NULL); }Was fehlt ist noch das Timer-Event zum Neuzeichnen, aber das ist hier sicher nicht so wichtig. Ich blicke bei OpenGL noch nichts ganz so durch, daher frage ich nochmal etwas genauer
ich bin ja schon froh, dass es mit einem OpenGL Window läuft 
-
Du rufst in der OnInitDialog nicht oglInitialize() auf. Das muss aber einmal geschehen. Liegts evtl. nur daran?
-
Ich werds mal testen. Ich schiebe es aber erstmal in meiner ToDo-Liste nach unten, ich teste erstmal NUR das zweite OGL-Fenster. Wenn das läuft versuche ich beide gleichzeitig, wenn was ist melde ich mich einfach nochmal

-
Mach das
An sich ist es halt wirklich so, dass du alles doppelt hast. Da wir doppeltes nicht mögen, lohnt sich dafür natürlich ne eigene Klasse^^
-
So, bin nun wieder an diesem Problem. Irgendwann muss es ja gelöst werden
Ich rätsel immernoch, wieso es 2 Pixeldeskriptoren sein müssen, weil in meinem bestehenden keine spezifischen Fensterinformationen drinstehen. Würde ich das machen, sähen beide Deskriptoren identisch aus.Mal eine andere Überlegung: Macht es Sinn, das OpenGL Control beim Verlassen des TabX zu zerstören und beim Entern von TabY neu zu createn? Darf man das mehrmals machen? Da käme ja dann dasselbe bei raus oder?
-
JPSelter schrieb:
So, bin nun wieder an diesem Problem. Irgendwann muss es ja gelöst werden
Ich rätsel immernoch, wieso es 2 Pixeldeskriptoren sein müssen, weil in meinem bestehenden keine spezifischen Fensterinformationen drinstehen. Würde ich das machen, sähen beide Deskriptoren identisch aus.OpenGL will nunmal ne Verbindung vom Rendercontext zunm Devicecontext und das für jede Verbindung, sprich also für jedes Fenster. Sozusagen "Liebes liebes OpenGL, rendere bitte in diesen DC mit diesen gesetzten Eigenschaften"
Und das geht nunmal über den Pixeldeskriptor. Das du dann zweimal den selben setzt, ist doch egal dabei.JPSelter schrieb:
Mal eine andere Überlegung: Macht es Sinn, das OpenGL Control beim Verlassen des TabX zu zerstören und beim Entern von TabY neu zu createn? Darf man das mehrmals machen? Da käme ja dann dasselbe bei raus oder?
Musst du halt mal testen. ich würd aber sagen ja musst du machen. Ein neuer Tab hat nen neuen Handle und für das neue Handle brauchst du nen neuen DeviceContext. Diesen musst dann wieder mit dem Rendercontext verbinden usw.
Wie gesagt einfach mal testen^^
-
OK, soweit so gut. Meine Software zeichnet nun beide, aber nur den, der zuerst erzeugt wird und danach NUR den, also das Tab, das zuerst angeklickt wird. Alles was jetzt noch fehlt, ist eine Destroy-Methode. Jetzt sehe ich wieder, wie wenig Ahnung ich von C++ habe
Wie zerstöre ich denn das OpenGL-Objekt wieder?if (m_tabctrlMain.GetCurSel()==1) { ((tabDialog2*)m_tabctrlMain.GetTab(1))->DestroyOpenGL(); // plus eine Abfrage ob es überhaupt schon ein Objekt gibt ((tabDialog2*)m_tabctrlMain.GetTab(1))->CreateOpenGL(); ((tabDialog2*)m_tabctrlMain.GetTab(1))->ActivateRenderTimer(); } if (m_tabctrlMain.GetCurSel()==2) { ((tabDialog2*)m_tabctrlMain.GetTab(2))->DestroyOpenGL(); // plus eine Abfrage ob es überhaupt schon ein Objekt gibt ((tabDialog3*)m_tabctrlMain.GetTab(2))->CreateOpenGL(); ((tabDialog3*)m_tabctrlMain.GetTab(2))->ActivateRenderTimer(); }So ein CreateOpenGL sieht im Moment so aus (Beispiel aus tabDialog2):
void tabDialog2::CreateOpenGL() { m_oglGraph = new COpenGLCtrl(); <---- hier wirds konstruiert m_oglGraph->SetOGLDrawType(0); m_boolTimerActive=false; GetDlgItem(IDC_OPENGL)->GetWindowRect(rect_opengl); ScreenToClient(rect_opengl); // Create OpenGL Control window m_oglGraph->oglCreate(rect_opengl, this); }Wie sieht das DestroyOpenGL() aus? Sowas wie m_oglGraph.destroy() oder so? Das gibt es leider nur nicht. Vielen Dank für die Hilfe!
-
Habs gleich selbst gefunden
Ich rufe einfach den Destruktor von COpenGLCtrl auf. Jetzt muss ich nur noch überprüfen, ob das Objekt vorher schon da war.
-
edit: ok hat sich ja erledigt

-
Leider noch nicht ganz. Irgendwie wird das OpenGL nicht richtig gekillt. Ein Wechsel zwischen Tab2 - Tab3 - Tab2 - Tab3 endet in einer Exception, zudem addieren sich immer 2MB zum RAM hinzu. Die Exception kommt laut dem Debugger aus der Zeile
CreateEx(0, className, "OpenGL", WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS, rect, parent, 0);
aus meinem OpenGLCreate. Wie kann ich das gesamte OpenGL killen? Gibts doch bestimmt Befehle für oder?
-
Mit Create legst du ein Windowsfenster an. Das hat noch nix mit OpenGL zu tun. Dieses sollte man auch wieder mit Destroy freigeben.
Dann holst du dir sicher irgendwo mit GetDC() nen Context. Dieses gibt man am Ende mit ReleaseDC wieder frei.
Und den Rendercontext löscht man mit wglDeleteContext. Das wäre dann das einzig OpenGL-spezifische.
-
Au mann, langsam drehe ich durch... kostet schonwieder viel zu viel zeit alles. In einem Tutorial steht, ich soll
ReleaseDC(hWnd,hdc)
benutzen, aber der Compiler meckert rum, er akzeptiert keine 2 Argumente. Dann lasse ich hWnd weg und nun meckert er rum
error C2664: 'CWnd::ReleaseDC' : cannot convert parameter 1 from 'HDC' to 'CDC *'
Gleich bei wglDeleteContext dann sicher dasselbe Spiel...
-
Wie holst du dir den DC?
Mit GetDC() oder mit GetDC(HWND); ?Bei zweiter Variante dann gib das frei mit **::**GetDC(HWND,HDC)
Ersteres ist nämlich ne Membermethode von CWnd, zweiteres ist ne WinAPI-Funktion
-
mit
hdc = GetDC()->m_hDC;
-
OK, hier hab ich was gefunden:
http://steinsoft.net/index.php?site=Programming/Tutorials/opengl_dialog&printable=1
Ist so ähnlich wie mein Code jetzt, sogar sehr ähnlich. Das Tutorial was ich benutzt habe ist leider wieder offline. Aber hiermit können wir schnell eine Antwort finden
Einfache Frage: Was würdet Ihr an diesem Tutorial verändern, damit man das Zielfenster während der Laufzeit ändern kann? Mein Problem ist einfach, dass ich da dieses "*parent" in ::Create sehe und dieses nur einmal aufgerufen wird. Also was muss verändert werden? Danke für weitere Hilfe!
-
Hm an sich nix^^
Der Code beschreibt ja ein OpenGL-Control, ob du dann nun 1, 2 oder 3 anlegst ist dabei egal.
Nur das Zeichnen in der OnPaint musst du anders realisieren, das du das zu zeichnende von außen setzen kannst.Was man nicht sieht momentan ist die Freigabe, aber die kann auch in der OpenGLDevice-Klassen "versteckt" sein.
-
Ich dachte, man könne nur eines davon haben? Am Anfang dieses Threads wurde das zumindest gesagt. Ich meiner Version dieser Klasse habe ich bereits eine Membervariable, die den Output steuert. Was gezeichnet wird, ist also nicht das Problem, sondern das "wohin". Ganz am Anfang hatte ich ja 2 Instanzen dieser Klasse, aber da bekam eine immer seltsame Streifen und Linien (wie ein TV das keinen Empfang hat)
*15 Minuten später*
Habe mal eben mit dem Typen von der oben verlinkten Seite gechattet. Er hat ein kleines Demoprogramm mit Code, wo er gleichzeitig in 9 Fenster rendert. Also das was ich suche. Er benutzt Threads, anscheinend klappts bei mir deshalb nicht gleichzeitig.
-
Also wenn das nur über Threads geht, dann ist seine Klassen nicht gerade die beste^^.
-
Ne, doch keine Threads. Habe seine Klasse nun an mein Programm angepasst. Es werden jetzt beide Statics gezeichnet
Allerdings bleiben beide schwarz
Beide Draw-Funktionen werden aber durchlaufen, na immerhin ein Fortschritt 