Jump to content
  • Advertisement
Sign in to follow this  
Meesh

problems with HDC passing in lesson 13

This topic is 4059 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi all, got a little problem I can't seem to solve. I am trying to rewrite lesson 13 into a class. I've already updated the code to be VS 8.0 compatible, but there's still a problem.
GLvoid CText::BuildFont(GLvoid)								
{
	HFONT	font;									
	HFONT	oldfont;								
	m_base = glGenLists(96);							

	font = CreateFont(	-24,							
						0,					
						0,					
						0,					
						FW_BOLD,				
						FALSE,					
						FALSE,					
						FALSE,					
						ANSI_CHARSET,				
						OUT_TT_PRECIS,				
						CLIP_DEFAULT_PRECIS,			
						ANTIALIASED_QUALITY,			
						FF_DONTCARE|DEFAULT_PITCH,		
						"Courier New");				

	if(font == NULL)	
		MessageBox(NULL, "newfont", "error", MB_OK);
	
	oldfont = (HFONT)SelectObject(m_hDC, font);           

	if(oldfont == NULL)	
		MessageBox(NULL, "oldfont", "error", MB_OK);
	
	if(!wglUseFontBitmaps(m_hDC, 32, 96,m_base))				
	{
		LPVOID lpMsgBuf;
		LPVOID lpDisplayBuf;
		DWORD dw = GetLastError(); 

		FormatMessage(
			FORMAT_MESSAGE_ALLOCATE_BUFFER | 
			FORMAT_MESSAGE_FROM_SYSTEM,
			NULL,
			dw,
			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
			(LPTSTR) &lpMsgBuf,
			0, NULL );

		lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, 
			(lstrlen((LPCTSTR)lpMsgBuf)+40)*sizeof(TCHAR)); 
		StringCchPrintf((LPTSTR)lpDisplayBuf, 
			LocalSize(lpDisplayBuf),
			TEXT("failed with error %d: %s"), 
			dw, lpMsgBuf); 
		MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK); 

		LocalFree(lpMsgBuf);
		LocalFree(lpDisplayBuf);
		ExitProcess(dw); 
	}
		
	SelectObject(m_hDC, oldfont);							
	DeleteObject(font);									
}

The 'oldfont' var is NULL after the SelectObject() call so that drops an error, but I don't think that's the cause. The wglUseFontBitmaps() call pops a messagebox saying: "failed with error 0: The operation completed successfully". I find this a bit confusing as it should only return false if it fails. But having no error is self-contradictory, don't you think? I rather think the problem has something to do with the 'HDC m_hDC' variable. I've tried the exact same code in a C-style manner, with m_hDC replaced with a global hdc variable, and the function worked swimmingly. So, am i passing stuff right when i do this in the constructor?:
CText::CText(HDC hdc)
{
	BuildFont();
	m_hDC = (HDC)hdc;
}

this has stumped me. I believe that HDC is a typedef for *HDC so theres no need to worry about data copying vs. direct data access when passing the variable as parameter. Any ideas to shed some light on this?

Share this post


Link to post
Share on other sites
Advertisement

BuildFont();
m_hDC = (HDC)hdc;



And what does that mean m_hDC is in BuldFont()? You should probably try doing FormatError() after SelectObject() fails, and you'll see that the HDC is invalid.

And it should really be:

CText::CText(HDC hdc) : m_hDC(hdc)
{
BuildFont();
}

Which will get rid of errors like this.

Share this post


Link to post
Share on other sites
Hehehe, I now see the error of my ways. That was pretty incompetent of me. Thanks for the quick reply =)

Share this post


Link to post
Share on other sites
Ok, now I'm stumped again.

I get no errors from the BuildFont() function, but there is nothing being displayed. I have removed some of the error checking code to make it easier to read, but wglUseFontBitmaps() does not return false, and the SelectObject() function returns the font properly now.

Posted is the full CText class and the calls to the class:


#ifndef __GL_TEXT_H_
#define __GL_TEXT_H_

#include <windows.h>
#include <stdio.h>
#include <stdarg.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glaux.h>

class CText
{
public:
CText();
CText(HDC hdc);
~CText();
GLvoid Print(float x, float y, const char *fmt, ...);

protected:
GLvoid BuildFont(GLvoid);
GLvoid KillFont(GLvoid);

HDC m_hDC;
GLuint m_base;
};

#endif




#include "text.hpp"

CText::CText()
{
}

CText::CText(HDC hdc) : m_hDC(hdc)
{
BuildFont();
}

CText::~CText()
{
KillFont();
}

GLvoid CText::BuildFont(GLvoid)
{
HFONT font;
HFONT oldfont;
m_base = glGenLists(96);

font = CreateFont( -24,
0,
0,
0,
FW_BOLD,
FALSE,
FALSE,
FALSE,
ANSI_CHARSET,
OUT_TT_PRECIS,
CLIP_DEFAULT_PRECIS,
ANTIALIASED_QUALITY,
FF_DONTCARE|DEFAULT_PITCH,
"Courier New");

oldfont = (HFONT)SelectObject(m_hDC, font);

wglUseFontBitmaps(m_hDC, 32, 96,m_base);

SelectObject(m_hDC, oldfont);
DeleteObject(font);
}

GLvoid CText::KillFont(GLvoid)
{
glDeleteLists(m_base, 96);
}

GLvoid CText::Print(float x, float y, const char *fmt, ...)
{
char text[256];
va_list ap;
int len;

if (fmt == NULL)
return;

va_start(ap, fmt);
len = _vscprintf(fmt, ap) + 1;
if(len > 256)
return;
vsprintf_s(text,len,fmt, ap);
va_end(ap);

glRasterPos2f(x, y);
glPushAttrib(GL_LIST_BIT);
glListBase(m_base - 32);
glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);
glPopAttrib();
}



Declared global:

CText TextPrinter



In my initialisation where ghdc is a global, working, HDC:

TextPrinter = CText(ghdc);



And finally the actual call: I do not tranformations, all matrices are loaded with identity matrices


glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glColor3f(0.1, 0.3, 0.9);
TextPrinter.Print(0.0, 0.0, "Hello Milla!");


SwapBuffers(ghdc);



Again, is this something obvious I'm missing or what? any help appreciated

Share this post


Link to post
Share on other sites
Here's where the problem probably lies:
TextPrinter = CText(ghdc);

Your CText() class doesn't have a copy constructor or an operator=. That means that this will call the CText constructor with ghdc passed to it to create a temporary variable, then call operator= to assign that variable TextPrinter (Which will just call operator= on all member variables as the default implementation), then the CText destructor will be called to destroy the temporary variable you created, which calls KillFont().

You'll have to implement a copy constructor and operator=, remove the KillFont() from the destructor and make sure you call it manually, or use some other method of doing this like using a pointer to a CText instead of a plain value, and optionally using a smart pointer with it.

Share this post


Link to post
Share on other sites
Thanks again. I seem to run into that problem all the time. I create a class, where I never want the default constructor to be called, only the parameterised ones. But when I create my instance I can't instantiate it with parameters (probably possible, but i don't know how yet. Still learning the intricacies of C vs C++)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!