Is using wglGetCurrentDC recommendable?

Started by
2 comments, last by CheeseMonger 19 years, 6 months ago
Hi, WGL function calls often require passing the HDC as a parameter. So far I've just passed the HDC of my program window all way down through the program hierarchy. Clearly this is not a nice solution, lots of repeating passing code and ultimately non-portable code. Then I heard of this thing called wglGetCurrentDC. My only question is: Is it recommandable? That is, can it "bug" on more complicated scenarios, such as using multiple windows? Thanks in advance! -- Mikko
Advertisement
wglGetCurrentDC() will return the device context you gave wglMakeCurrent(), so as long as you have already made a call to wglMakeCurrent() in the same thread, wglGetCurrentDC() will return the device context currently associated with your rendering context.

Use wglGetCurrentContext() to get your current rendering context.
- CheeseMonger
I found that using a central data storage helps a tad with problems like this.
I store my hDC in this container and can retrieve it by identifier (DATA_NAME_HDC). The hDC is put there when the window is created.
In order to expand to multiple windows you could use different identifiers.
However, The MSDN states that your function retrieves the HDC of the calling thread. That gives me the impression that every OpenGL window in an application will have its own seperate thread, thus, as long as you call wglGetCurrentDC from the right thread, it won't "bug" on you.

That all said, I'm not a big fan of using platform code in my actual game code. So I always try to mask the origin of OS depending parameters, such as the hDC.
Ofcourse, I don't know what you are building, so this might not be an option to you.

Anyway, as for my good deed for today: (makes me sleep well tonight ;))

#ifndef DATA_H#define DATA_H/*****************************************************************INCLUDES*****************************************************************/#include <vector>/*****************************************************************DEFINES*****************************************************************/#define DATA_TYPE_NONE		0#define DATA_TYPE_HDC		1#define DATA_TYPE_GRAPHICSETTINGS	2#define DATA_TYPE_FPS	3/*****************************************************************CLASS PROTOTYPES*****************************************************************//**A base class for the Data class. This gives the CDC the chance to manage data in a generic way.This class defines a type which tells the retriever of which type the Data-class is.TODO:Give this class a property name and type. The type would indicate the data type of the Data object.The name would indicate what kind of data is stored. For example the HDC*/class DataContainer{public:	DataContainer();	virtual ~DataContainer();	void setType(int t);	int getType();private:	int type;	/**< Indicates teh type of data we are dealing with. For example a HDC. */};/**This class is a container for a piece of data. It provides a getter and setter for this value.The templated type gives the type of the contained piece of data. For example a float.*/template <typename t>class Data : public DataContainer{public:	Data() { }	~Data() { }	t get() { return value; };	/**< returns the data contained in the parameter value. */	void set(t thingy) { value = thingy; };	/**< sets the value parameter to a certain value. */private:	t value;	/**< The contained data */};/**CDC stands for Central Data ContainerA central place to store certain information that can be retrieved by other components.Prime example is the hDC (Device Context Handle) which is used by many Windows calls. This Handle is stored in the Window when the window is created, however is needed for many GDI calls.TODO:Think about the CDC using an IDManager lay-out for getting and adding data.Derive the CDC from Singleton base class*/class CDC{public:	static CDC* INSTANCE();	DataContainer* getData(int type);	void addData(DataContainer* c);private:	CDC();	~CDC();	std::vector<DataContainer*> data;	/**< A list of DataContainers that are managed by the CDC */	static CDC* instance;	/**< Singletonian instance */};#endif


#include "data.h"/***********************************************CLASS DATACONTAINER***********************************************//***/DataContainer::DataContainer(){	type = DATA_TYPE_NONE;}/***/DataContainer::~DataContainer(){}/**Sets the type of information stored in the data container. For example HDC.@param t An integer idicating the type. (see definitions)*/void DataContainer::setType(int t){	type = t;}/**Returns the type of information stored in the data container@return Returns an integer value containing the type of data*/int DataContainer::getType(){	return type;}/***********************************************CLASS DATA***********************************************//***********************************************CLASS CDC***********************************************/CDC* CDC::instance = NULL;CDC* CDC::INSTANCE(){	if (instance == NULL)		instance = new CDC();	return instance;}CDC::CDC(){}CDC::~CDC(){}/**Adds a DataContainer to the list of data.If the data already exists (for example, there already is a HDC in the CDC) then the data is overwritten.@param c The container to be added to the list.*/void CDC::addData(DataContainer* c){	int i;	if (c)	{		if (c->getType() == DATA_TYPE_NONE)			return;	// we do not wish data of an undefined type;		for (i=0; i<data.size(); i++)		{			if (data->getType() == c->getType())			{				delete data;				data = c;				return;			}		}		data.push_back(c);	}	}/**Retrieves a pointer to a DataContainer containing the data of a specific type.@param type The type of data to be retrieved. For example the HDC.@return Returns a pointer to the container that holds this data. If the data was not found this function will return NULL.*/DataContainer* CDC::getData(int type){	int i;	for (i=0; i<data.size(); i++)	{		if (data->getType() == type)			return data;	}	return NULL;}


The classes need a bit of work still (it all being a work in progress), but you get the general gist of it.

Data<HDC>* d = new Data<HDC>();d->setType(DATA_TYPE_HDC);d->set(window->hDC);CDC::INSTANCE()->addData(d);

Data<HDC>* d = (Data<HDC>*)CDC::INSTANCE()->getData(DATA_TYPE_HDC);if (d){	hDC = d->get();}


I'm sorry I couldn't answer your question about wglGetCurrentDC being a good choice. However, I hope I have given an alternative to your current methods.
STOP THE PLANET!! I WANT TO GET OFF!!
Quote:Original post by Structural
That gives me the impression that every OpenGL window in an application will have its own seperate thread...


Not necessarily, it's just that contexts can only made current for OpenGL to render to in one thread at a time.

This is why in a multi-threaded and single windowed GL application, you must make the contexts current again in the new thread before you can render. I would imagine that games would only use the one thread to render (other threads doing background loading and such) so this issue would rarely arise.
- CheeseMonger

This topic is closed to new replies.

Advertisement