Sign in to follow this  

problems with my win32 class

This topic is 4595 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

I'm trying to create a simple class in C++ so that all I'd have to do is include this file in future files and call a few functions to setup a window, but I have one error so far that I cannot understand. This is the line... winclass.lpfnWndProc = WindowProc; and this is the error... error C2440: '=' : cannot convert from 'long (__stdcall initwin::*)(struct HWND__ *,unsigned int,unsigned int,long)' to 'long (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long)' There is no context in which this conversion is possible I see that the main problem is (_stdcall initwin::*) to (_stdcall *), and it looks to me like the only way to get rid of this is to leave something out of my class. What do I have to do to be able to keep all variables/struct declarations and functions inside of a class declaration so I can avoid using globals? Here's the (incomplete) code as it is now:
#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <windowsx.h>
#include <mmsystem.h>
#include <stdlib.h>
#include <stdio.h>
#include <ddraw.h>
#include <math.h>

class initwin
{
private:
	HWND				hwindow;		UINT		msg2;
	HINSTANCE			hinst;			WPARAM		wparam;
	WNDCLASSEX			winclass;		LPARAM		lparam;
	MSG					msg;
public:
	initwin();
	LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
	WNDCLASSEX SetWinclass(WNDCLASSEX winclass);
};

initwin::initwin()
{
	hwindow = NULL;
	hinst = NULL;
}

LRESULT CALLBACK initwin::WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
PAINTSTRUCT		ps;
HDC				hdc;

switch(msg)
	{	
	case WM_CREATE: 
        {
		return(0);
		} break;
  

	case WM_PAINT: 
		{
		hdc = BeginPaint(hwnd,&ps);	 
        EndPaint(hwnd,&ps);
		return(0);
   		} break;

	case WM_DESTROY: 
		{
		PostQuitMessage(0);
		return(0);
		} break;

	default:break;

    } // end switch

return (DefWindowProc(hwnd, msg, wparam, lparam));

} // end WinProc

WNDCLASSEX initwin::SetWinclass(WNDCLASSEX winclass)
{
	winclass.cbSize         = sizeof(WNDCLASSEX);
	winclass.style			= CS_DBLCLKS | CS_OWNDC | 
							  CS_HREDRAW | CS_VREDRAW;
	winclass.lpfnWndProc	= WindowProc;
	winclass.cbClsExtra		= 0;
	winclass.cbWndExtra		= 0;
	winclass.hInstance		= hinst;
	winclass.hIcon			= LoadIcon(NULL, IDI_APPLICATION);
	winclass.hCursor		= LoadCursor(NULL, IDC_ARROW); 
	winclass.hbrBackground	= (HBRUSH)GetStockObject(BLACK_BRUSH);
	winclass.lpszMenuName	= NULL;
	winclass.lpszClassName	= "C++ window class";
	winclass.hIconSm        = LoadIcon(NULL, IDI_APPLICATION);
	return winclass;
}

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
					LPSTR lpCmdLine, int nShowCmd)
{
	return 0;
}

Share this post


Link to post
Share on other sites
I don't know if this will work (just a shot in the dark here), but trying putting:

winclass.lpfnWndProc = this.WindowProc;

If that doesn't work, then just remove WindowProc from the class and make it an external function. It doesn't hurt to have a couple of globals, just make sure that you don't overdo them. Same with classes.

Share this post


Link to post
Share on other sites
Every function inside a class has a hidden last parameter where this (the pointer to the class) is passed. That's why the compiler complains. The line:

winclass.lpfnWndProc = WindowProc;

expects to see a WNDPROC function pointer and you assign it something which is not a WNDPROC function pointer because of the hidden parameter.

There are a few ways to get around this problem. My favorite is to have the WndProc function outside the class and pass it as a parameter to an Init function of my class. It can then be assigned to the lpfnWndProc without the compiler complaining.

You can always have all the initialisation and windows creation/message handling stuff in a separate file and just add it to your workspace everytime you start a new project, without using classes. All you have to do is call the Init function if all you need a window class for is initialisation.

Share this post


Link to post
Share on other sites
I guess I'll have to go with the suggestion to leave it out of a class, since declaring the function as static inside a class causes another error. Now that I think of it, I could just use a "initwin.cpp" file to put all of my initialization functions into.

Now since that's apparently it, could anyone tell me if I could use this kind of code in unmanaged C++.net? I've googled for tutorials, but couldn't really find something besides using C++.net for managed code or for sample applications. I had asked this type of question before and didn't really get an answer...

Share this post


Link to post
Share on other sites
I think I've found a solution for the time being that cuts down on the number of lines of code in the WinMain function. All it requires are for the same variable/struct declarations within WinMain as in the globals.

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <windowsx.h>
#include <mmsystem.h>
#include <stdlib.h>
#include <stdio.h>
#include <ddraw.h>
#include <math.h>

HINSTANCE hinst;
WNDCLASSEX winclass;
HWND hwnd;
MSG msg;
HDC hdc;
int x = 0; int w = 400;
int y = 0; int h = 300;
const char *wcname = "C++ window class";
const char *wtitle = "Test window...";

LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
PAINTSTRUCT ps;
HDC hdc;

switch(msg)
{
case WM_CREATE:
{
return(0);
} break;


case WM_PAINT:
{
hdc = BeginPaint(hwnd,&ps);
EndPaint(hwnd,&ps);
return(0);
} break;

case WM_DESTROY:
{
PostQuitMessage(0);
return(0);
} break;

default:break;

}

return (DefWindowProc(hwnd, msg, wparam, lparam));

}

void SetWinclass(WNDCLASSEX &winclass, HINSTANCE &hinst, HWND &hwnd)
{

winclass.cbSize = sizeof(WNDCLASSEX);
winclass.style = CS_DBLCLKS | CS_OWNDC |
CS_HREDRAW | CS_VREDRAW;
winclass.lpfnWndProc = WindowProc;
winclass.cbClsExtra = 0;
winclass.cbWndExtra = 0;
winclass.hInstance = hinst;
winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
winclass.lpszMenuName = NULL;
winclass.lpszClassName = wcname;
winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

RegisterClassEx(&winclass);

hwnd = CreateWindowEx(NULL, wcname, wtitle, WS_OVERLAPPEDWINDOW | WS_VISIBLE,
x, y, w, h, NULL, NULL, hinst, NULL);

hdc = GetDC(hwnd);
}

int HandleMsg(MSG &msg)
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if (msg.message == WM_QUIT)
return 1;

TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nShowCmd)
{
HWND hWnd = NULL;
HDC hDC = NULL;
WNDCLASSEX winClass;
HINSTANCE hInst;
MSG mSg;
SetWinclass(winClass, hInst, hWnd);
while(TRUE)
{
if(HandleMsg(mSg)==1)
break;

SetTextColor(hdc, RGB(rand()%256,rand()%256,rand()%256));
SetBkColor(hdc, RGB(0,0,0));
SetBkMode(hdc, TRANSPARENT);
TextOut(hdc,rand()%400,rand()%400, "GDI Text Demo!", strlen("GDI Text Demo!"));

Sleep(10);
}
ReleaseDC(hWnd, hDC);
return (msg.wParam);
}

Share this post


Link to post
Share on other sites
Another option would be to pass a pointer of the WNDPROC to your original class


void initwin::SetWinclass(WNDPROC proc)
{
hinst =GetModuleHandle(NULL);

winclass.cbSize = sizeof(WNDCLASSEX);
winclass.style = CS_DBLCLKS | CS_OWNDC |
CS_HREDRAW | CS_VREDRAW;
winclass.lpfnWndProc = proc;
winclass.cbClsExtra = 0;
winclass.cbWndExtra = 0;
winclass.hInstance = hinst;
winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
winclass.lpszMenuName = NULL;
winclass.lpszClassName = "C++ window class";
winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
}




Hmm had to fix that a bit hope that doesn't have to many errors [lol]
This is as long as you don't mind having the window procedure outside your class of course [smile]

Share this post


Link to post
Share on other sites

This topic is 4595 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this