Wie MFC Control in den Vordergrund bekommen?



  • Nein, klappt nicht. Hier mein Code:

    GetDlgItem(IDC_OPENGL)->SetWindowPos(&CWnd::wndTop,0,0,200,200,NULL);
    

    Das TabControl ist immernoch im Vordergrund.



  • Benutz mal statt CWnd::wndTop den zeiger deines tab controls



  • Ne, geht leider immernoch nicht. Egal, ob ich &DynTabCtrl oder &COpenGLCtrl (meine OpenGL-Klasse) benutze, das Image-Control ist immer im Hintergrund. Die einzige Chance, es sichtbar zu machen, ist das TabControl auf Transparent zu setzen, aber dann sehe ich es ja immer, egal welcher Tab aktiviert ist.

    Macht es dann Sinn, mit dem Wechsel eines Tabs das OpenGLCtrl immerwieder zu createn und zu destroyen. Kann man so ohne weiteres während der Laufzeit machen, oder darf man das nur beim Start oder beim Beenden einer Applikation? Andererseits würde das mein zweites Problem lösen: Ich brauche 2 OpenGL-Canvas. Statt 2 zu createn könnte ich dann immer eines createn, das andere destroyen usw. Wie gefragt, macht das Sinn?





  • Das gibt mir die Fehlermeldung

    error C2664: 'SetWindowPos' : cannot convert parameter 1 from 'struct HWND__ *' to 'const class CWnd *'

    Der "Zeiger_auf_Fensterobjekt" ist doch graphTab->m_iOGL oder? Ich habe folgende Komponenten in dieser Hierarchie:

    - der CDialog (Membervariable: m_pMainWnd, Klasse: CMyApp)
    - das TabControl (Membervariable: m_gTabCtrl, Klasse: DynTabCtrl)
    - Tab Index 2 (Membervariable: graphTab, Klasse: MyDialog2)
    - Image-Control (OpenGL Canvas) (Membervariable: m_iOGL, Klasse: MyDialog2)
    - OpenGL-Canvas (Membervariable: OpenGLCtrl, Klasse: COpenGLCtrl)

    Das oben verlinkte Artikel verwirrt mich nun irgendwie total...



  • http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_mfc_cwnd.3a3a.setwindowpos.asp

    BOOL CWnd::SetWindowPos
    (
       const CWnd* pWndInsertAfter,
       int x,
       int y,
       int cx,
       int cy,
       UINT nFlags 
    );
    

    pWndInsertAfter
    Identifies the CWnd object that will precede this CWnd object in the Z-order. This parameter can be a pointer to a CWnd or a Pointer to one of the following values:

    wndTop Places the window at the top of the Z-order.

    wndTopMost Places the window above all nontopmost windows. The window maintains its topmost position even when it is deactivated.

    GetDlgItem(IDC_OPENGL)->SetWindowPos(&CWnd::wndTopMost,0,0,200,200,???);
    GetDlgItem(IDC_OPENGL)->SetWindowPos(&CWnd::wndTop,0,0,200,200,???);



  • Nein, klappt nicht. Vielleicht liegt hier auch ein Missverständnis vor: Ich meine nicht, dass mein WINDOW im Hintergrund ist, sondern das Image-Control INNERHALB desselben Fensters hinter allen anderen Controls liegt, in meinem Fall verdeckt das TabControl das Image-Control.



  • Doch, das klappt noch, probier mal Folgendes (hier am Beispiel von drei sich überlappenden Buttons IDC_BUTTON2, IDC_BUTTON3, IDC_BUTTON4 ausprobiert). Wichtig ist das Invalidate(), ansonsten wird nicht neugezeichnet. Vielleicht liegt es einfach nur daran. Du hast zwei getrennte Ebenen, in denen Du mit CWnd::wndTop nach oben rangieren kannst, nämlich die Ebene der "NonTopMost"-Fenster und die Ebene der "TopMost"-Fenster, dürfte in Deinem Fall aber keine Rolle spielen. Ein TopMost-Parent-Fenster hat automatisch alle Child-Fenster auch TopMost. Nur ein NonTopMost-Parent-Fenster kann beide Typen ( TopMost und NonTopMost) von Child-Fenster haben. (siehe Code):

    void CTestDlg::OnChangeOrder() 
    {
    		static BYTE zahl    = 0;
    		const  BYTE ZAHLMAX = 2;
    
    		for(int i=0; i<=ZAHLMAX; ++i)
    		{
    			GetDlgItem(IDC_BUTTON2 + i)->SetWindowPos(&CWnd::wndNoTopMost,0,0,200,200, SWP_NOMOVE|SWP_NOSIZE   );
    		}
    
    		GetDlgItem(IDC_BUTTON2 + zahl)->SetWindowPos(&CWnd::wndTopMost,0,0,200,200, SWP_NOMOVE|SWP_NOSIZE   );
    		GetDlgItem(IDC_BUTTON2 + zahl)->SetWindowPos(&CWnd::wndTop,0,0,200,200, SWP_NOMOVE|SWP_NOSIZE   );
    		GetDlgItem(IDC_BUTTON2 + zahl)->Invalidate(); //Wichtig
    
    		zahl++;
    		if(zahl > ZAHLMAX) 
    			zahl = 0;
    }
    

    sollte auch damit gehen:

    void CStaticTextDlg::OnChangeOrder() 
    {
    		static BYTE zahl    = 0;
    		const  BYTE ZAHLMAX = 2;
    
    		/*
    		for(int i=0; i<=ZAHLMAX; ++i)
    		{
    			GetDlgItem(IDC_BUTTON2 + i)->SetWindowPos(&CWnd::wndNoTopMost,0,0,200,200, SWP_NOMOVE|SWP_NOSIZE   );
    		}
    		*/
    		//GetDlgItem(IDC_BUTTON2 + zahl)->SetWindowPos(&CWnd::wndTopMost,0,0,200,200, SWP_NOMOVE|SWP_NOSIZE   );
    		GetDlgItem(IDC_BUTTON2 + zahl)->SetWindowPos(&CWnd::wndTop,0,0,200,200, SWP_NOMOVE|SWP_NOSIZE   );
    		GetDlgItem(IDC_BUTTON2 + zahl)->Invalidate();
    
    		zahl++;
    		if(zahl > ZAHLMAX) 
    			zahl = 0;
    }
    

    Mit den sich überlappenden Buttons (sind ja auch CWnd) klappt es bestens.



  • Danke für die ausführliche Antwort. Ich teste das morgen mal durch, jetzt ist es etwas spät 😉
    Falls es nicht klappen sollte: Liegts vielleicht ganz einfach nicht am Image-Control sondern am OpenGL? Immerhin muss ich das Control auf "invisible" setzen, damit man überhaupt das OpenGL-Canvas sehen kann. Vielleicht hat hier OpenGL ein Problem, das sich nicht über "einfache" MFC Funktionen lösen lässt.
    Ich teste es morgen aber wie gesagt mal ausführlich durch. Irgendwie MUSS es ja klappen.



  • Ich gebs in diesem Thread vorerst auf... es wird nicht klappen. Wie ich vermutet habe, muss es eine Eigenheit von OpenGL sein. Denn:
    Wenn ich ein normales Static-Text zwischen 2 Groupboxes setze ist der Text im Vordergrund, es überdeckt die Groupboxes. Für OpenGL muss ich es aber wieder invisible setzen und es erscheint stattdessen eine grüne Box, die aber wieder HINTER den Groupboxes liegt. Und das alles obwohl ich nichts an der Reihenfolge der Ebenen geändert habe. Ich werde mich also mal in einem OpenGL Forum umsehen. Danke trotzdem für die Hilfe!

    EDIT: Ich habe mir mal die Create-Routine meiner OpenGL-Klasse näher angesehen. Dort wird ein komplett neues Fenster als Child erzeugt:

    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_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS, rect, parent, 0);
    
        // Set initial variables' values
        m_oldWindow    = rect;
        m_originalRect = rect;
    
        hWnd = parent;
    }
    

    Irgendwie dadrin muss ich was ändern, dann klappt es sicher. Bloss was 😃



  • Halli hallo, ich hab mir mal vor einer Weile eine abstrakte Window-Klasse für OGL erstellt vieleicht hilft Dir das ja weiter, ich poste einfach mal die cpp, da steht eigentlich alles drin was wichtig ist. Probleme, das ich erst ein control auf unvisible setzten musste hatte ich damit bis jetzt noch nicht.

    // WndGL.cpp: Implementierungsdatei
    //
    
    #include "stdafx.h"
    #include "WndGL.h"
    
    // CWndGL
    
    IMPLEMENT_DYNAMIC(CWndGL, CWnd)
    
    CWndGL::CWndGL()
    : m_pRenderThread(NULL)
    {
    
    }
    
    CWndGL::~CWndGL()
    {
    }
    
    BEGIN_MESSAGE_MAP(CWndGL, CWnd)
    	ON_WM_DESTROY()
    END_MESSAGE_MAP()
    // CWndGL-Meldungshandler
    
    BOOL CWndGL::PreCreateWindow(CREATESTRUCT& cs)
    {
    	WNDCLASS wc;
    	HINSTANCE hInstance	= GetModuleHandle(NULL);				// Grab An Instance For Our Window
    
    	wc.style			= CS_HREDRAW | CS_VREDRAW | CS_OWNDC; 
    	wc.lpfnWndProc		= AfxWndProc;					        // WndProc Handles Messages
    	wc.cbClsExtra		= 0;									// No Extra Window Data
    	wc.cbWndExtra		= 0;									// No Extra Window Data
    	wc.hInstance		= hInstance;							// Set The Instance
    	wc.hIcon			= LoadIcon(NULL, IDI_WINLOGO);			// Load The Default Icon
    	wc.hCursor			= LoadCursor(NULL, IDC_ARROW);			// Load The Arrow Pointer
    	wc.hbrBackground	= NULL;									// No Background Required For GL
    	wc.lpszMenuName		= NULL;									// We Don't Want A Menu
    	wc.lpszClassName	= m_strClassName;
    
    	AfxRegisterClass(&wc);										// Attempt To Register The Window Class
    
    	cs.style			= CS_HREDRAW | CS_VREDRAW | CS_OWNDC |WS_POPUP;//| //WS_OVERLAPPEDWINDOW;	// Required Window Style
    	cs.hInstance		= hInstance;							// Set The Instance
    	cs.hMenu			= NULL;									// We Don't Want A Menu
    	cs.lpszClass        = m_strClassName;								// Set The Class Name
    	cs.dwExStyle        = WS_EX_APPWINDOW;
    	return CWnd::PreCreateWindow(cs);
    }
    
    UINT CWndGL::ThreadFunc(LPVOID lpv)
    {
    	CWndGL* pThis = reinterpret_cast<CWndGL*>(lpv);
    	pThis->m_hRC  = wglCreateContext( pThis->m_hDC );
    	wglMakeCurrent(pThis->m_hDC, pThis->m_hRC);
    	MSG msg;
    
    	pThis->GLInit();
    		while(true)
    		{
    			PeekMessage( &msg, NULL, 0, 0, PM_REMOVE );	// Is There A Message Waiting?
    			if ( msg.message == WM_QUIT )				// Have We Received A Quit Message?
    			{
    				return FALSE;
    			}
    			else									// If Not, Deal With Window Messages
    			{
    				TranslateMessage(&msg);				// Translate The Message
    				DispatchMessage(&msg);				// Dispatch The Message
    			}
    
    			pThis->GLPreRender();
    			pThis->GLRender();
    			pThis->GLPostRender();			
    			pThis->GLSwapBuffers();
    		}
    
    	return TRUE;
    }
    
    void CWndGL::GLSwapBuffers()
    {
    	::SwapBuffers( m_hDC );
    }
    
    BOOL CWndGL::Create(LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
    {
    	m_strClassName = "OpenGL";
    
    	GLuint glPixelFormat;
    	PIXELFORMATDESCRIPTOR PFD = 
    	{
    		sizeof(PIXELFORMATDESCRIPTOR),				// Size Of This Pixel Format Descriptor
    		1,											// Version Number
    		PFD_SUPPORT_OPENGL |						// Format Must Support OpenGL
    		PFD_DOUBLEBUFFER,							// Must Support Double Buffering
    		PFD_TYPE_RGBA,								// Request An RGBA Format
    		32,										    // Select Our Color Depth
    		0, 0, 0, 0, 0, 0,							// Color Bits Ignored
    		0,											// No Alpha Buffer
    		0,											// Shift Bit Ignored
    		0,											// No Accumulation Buffer
    		0, 0, 0, 0,									// Accumulation Bits Ignored
    		16,											// 16Bit Z-Buffer (Depth Buffer)  
    		0,											// No Stencil Buffer
    		0,											// No Auxiliary Buffer
    		PFD_MAIN_PLANE,								// Main Drawing Layer
    		0,											// Reserved
    		0, 0, 0										// Layer Masks Ignored
    	};		
    
    	if ( CWnd::CreateEx(NULL, m_strClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID) )
    	{
    
    		m_hDC           = GetDC()->m_hDC;						// Did We Get A Device Context?
    		glPixelFormat   = ChoosePixelFormat( m_hDC, &PFD );		// Did Windows Find A Matching Pixel Format?
    
    		SetPixelFormat( m_hDC, glPixelFormat, &PFD );				// Are We Able To Set The Pixel Format?
    
    		m_pRenderThread = AfxBeginThread( CWndGL::ThreadFunc ,this);	
    
    		return TRUE;
    	}
    	return FALSE;
    }
    
    void CWndGL::OnDestroy()
    {
    	if (m_pRenderThread)m_pRenderThread->PostThreadMessageA( WM_QUIT,0,0);
    
    	WaitForSingleObject(m_pRenderThread->m_hThread, INFINITE);
    
    	if (m_hRC)											// Do We Have A Rendering Context?
    	{
    		wglMakeCurrent(NULL,NULL);					// Are We Able To Release The DC And RC Contexts?
    		wglDeleteContext(m_hRC);						// Are We Able To Delete The RC?
    		m_hRC=NULL;										// Set RC To NULL
    	}
    
    	if (m_hDC)
    	{
    		ReleaseDC(CDC::FromHandle(m_hDC));					// Are We Able To Release The DC
    		m_hDC=NULL;										// Set DC To NULL
    	}
    	CWnd::OnDestroy();
    
    }
    

    Viel Glück 😉



  • Yiiiiippiiieeee! Na endlich, es klappt! Das Problem war der Aufruf

    m_oglWindow.oglCreate(rect, this);

    das im OnInitDialog() der Hauptklasse stand und daher die Hauptklasse als Parent (=this) übergeben hat. Ich habe im TabControl aber für jedes Tab eine eigene Child-Klasse mit eigenen Formularen und Controls. Habe also der Child-Klasse ein OnInitDialog() verpasst und alle Init-Aufrufe von OpenGL dareingeschrieben (statt in die Hauptklasse) und siehe da, das OpenGL Canvas ist endlich zu sehen und verschwindet wieder, wenn ich das Tab wechsel 🙂 Puh, endlich gehts weiter...



  • 🙂


Anmelden zum Antworten