C++ win32 OpenGL Mouse Movement

closed account (DSvMDjzh)
I am attempting to create a program that tracks mouse movement and then draws a line between 2 coordinates every 20ms. So my troubles:
1: Converting the mouse coordinates to the same type that openGL uses
2: Getting it to keep the previous line(Basically I want a continuous line)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// program main loop
	while ( !quit )
	{
		
		// check for messages
		if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE )  )
		{
			
			// handle or dispatch messages
			if ( msg.message == WM_QUIT ) 
			{
				quit = TRUE;
			} 
			else 
			{
				TranslateMessage( &msg );
				DispatchMessage( &msg );
			}
			
		} 
		else 
		{
			
			// OpenGL animation code goes here
			
			glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
			glClear( GL_COLOR_BUFFER_BIT );
			
			glPushMatrix();

			glBegin(GL_LINE_STRIP);
			glColor3f(1.0f,0.0f,0.0f); glVertex2f(-1.0,-1.0);
			//glColor3f(1.0f,0.0f,0.0f); glVertex2f(0.3,0.4);
			glColor3f(1.0f,0.0f,0.0f); glVertex2f(xPosg, yPosg);
			glEnd();

			glPopMatrix();
			
			SwapBuffers( hDC );
			
		}
		
	}
	
	// shutdown OpenGL
	DisableOpenGL( hWnd, hDC, hRC );
	
	// destroy the window explicitly
	DestroyWindow( hWnd );
	
	return msg.wParam;
	
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// Window Procedure

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	
	switch (message)
	{
		
	case WM_CREATE:
		return 0;
		
	case WM_CLOSE:
		PostQuitMessage( 0 );
		return 0;
		
	case WM_DESTROY:
		return 0;
		
	case WM_KEYDOWN:
		switch ( wParam )
		{
			
		case VK_ESCAPE:
			PostQuitMessage(0);
			return 0;
			
		}
		return 0;

	case WM_MOUSEMOVE:
		xPos = GET_X_LPARAM(lParam); 
		yPos = GET_Y_LPARAM(lParam);
		//This is where coords should change to openGL coords
		xPosg = xPos;
		yPosg = yPos;
		return 0;

	default:
		return DefWindowProc( hWnd, message, wParam, lParam );
			
	}
	
}


Right now, just getting the program to draw a line with one fixed coordinate while following my cursor would be good.

Thanks,
Josh
This should be in the Windows Forum for future referance, the guys here seem to mostly prefer Non-API specific questions.

I don't see where you are stuck, maybe because your are using GET_X_LPARAM() instead of this function?:

GetMouseMovePointsEx()
http://msdn.microsoft.com/en-us/library/ms646259(v=VS.85).aspx
1. That depends on the coordinate system you've set up. Have you ever called glOrtho or gluPerspective or something like that? If yes, post that part. If no, try xPosg = (2.0*xPos/screen_width -1); and yPosg = (2.0*yPos/screen_height -1);. This converts mouse coordinates from range [0; screen_width) to (-1; 1). It could be (1; -1) though. I'm not sure..

2. To do this you have to store each point somewhere. For example std::vector.
closed account (DSvMDjzh)
The entire code so far is this
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#include <windows.h>
#include <windowsx.h>
#include <gl/gl.h>


// Function Declarations

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
void EnableOpenGL(HWND hWnd, HDC * hDC, HGLRC * hRC);
void DisableOpenGL(HWND hWnd, HDC hDC, HGLRC hRC);


//global variables
int xPos,yPos,xPosg,yPosg;

// WinMain

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
				   LPSTR lpCmdLine, int iCmdShow)
{
	WNDCLASS wc;
	HWND hWnd;
	HDC hDC;
	HGLRC hRC;
	MSG msg;
	BOOL quit = FALSE;
	
	
	// register window class
	wc.style = CS_VREDRAW;	//CS_OWNDC;
	wc.lpfnWndProc = WndProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = hInstance;
	wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
	wc.hCursor = LoadCursor( NULL, IDC_ARROW );
	//wc.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH );
	//wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wc.lpszMenuName = NULL;
	wc.lpszClassName = "GLSample";
	RegisterClass( &wc );
	
	// create main window
	hWnd = CreateWindow( 
		"GLSample", "OpenGL Sample", 
		WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE,
		//WS_TILEDWINDOW,
		0, 0, 1280, 1024,
		NULL, NULL, hInstance, NULL );
	
	// enable OpenGL for the window
	EnableOpenGL( hWnd, &hDC, &hRC );
	
	// program main loop
	while ( !quit )
	{
		
		// check for messages
		if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE )  )
		{
			
			// handle or dispatch messages
			if ( msg.message == WM_QUIT ) 
			{
				quit = TRUE;
			} 
			else 
			{
				TranslateMessage( &msg );
				DispatchMessage( &msg );
			}
			
		} 
		else 
		{
			
			// OpenGL animation code goes here
			
			glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
			glClear( GL_COLOR_BUFFER_BIT );
			
			glPushMatrix();

			glBegin(GL_LINE_STRIP);
			glColor3f(1.0f,0.0f,0.0f); glVertex2f(-1.0,-1.0);
			//glColor3f(1.0f,0.0f,0.0f); glVertex2f(0.3,0.4);
			glColor3f(1.0f,0.0f,0.0f); glVertex2f(xPosg, yPosg);
			glEnd();

			glPopMatrix();
			
			SwapBuffers( hDC );
			
		}
		
	}
	
	// shutdown OpenGL
	DisableOpenGL( hWnd, hDC, hRC );
	
	// destroy the window explicitly
	DestroyWindow( hWnd );
	
	return msg.wParam;
	
}

// Window Procedure

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	
	switch (message)
	{
		
	case WM_CREATE:
		return 0;
		
	case WM_CLOSE:
		PostQuitMessage( 0 );
		return 0;
		
	case WM_DESTROY:
		return 0;
		
	case WM_KEYDOWN:
		switch ( wParam )
		{
			
		case VK_ESCAPE:
			PostQuitMessage(0);
			return 0;
			
		}
		return 0;

	case WM_MOUSEMOVE:
		xPos = GET_X_LPARAM(lParam); 
		yPos = GET_Y_LPARAM(lParam);
		//This is where coords should change to openGL coords
		xPosg = (2.0*xPos/1280 -1);
		yPosg = (2.0*yPos/1040 -1);
		return 0;

	default:
		return DefWindowProc( hWnd, message, wParam, lParam );
			
	}
	
}

// Enable OpenGL

void EnableOpenGL(HWND hWnd, HDC * hDC, HGLRC * hRC)
{
	PIXELFORMATDESCRIPTOR pfd;
	int format;
	
	// get the device context (DC)
	*hDC = GetDC( hWnd );
	
	// set the pixel format for the DC
	ZeroMemory( &pfd, sizeof( pfd ) );
	pfd.nSize = sizeof( pfd );
	pfd.nVersion = 1;
	pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
	pfd.iPixelType = PFD_TYPE_RGBA;
	pfd.cColorBits = 24;
	pfd.cDepthBits = 16;
	pfd.iLayerType = PFD_MAIN_PLANE;
	format = ChoosePixelFormat( *hDC, &pfd );
	SetPixelFormat( *hDC, format, &pfd );
	
	// create and enable the render context (RC)
	*hRC = wglCreateContext( *hDC );
	wglMakeCurrent( *hDC, *hRC );
	
}

// Disable OpenGL

void DisableOpenGL(HWND hWnd, HDC hDC, HGLRC hRC)
{
	wglMakeCurrent( NULL, NULL );
	wglDeleteContext( hRC );
	ReleaseDC( hWnd, hDC );
}


@hamsterman I assume screen_width and screen_height are 1280/1040? Also I attempted to put in your code, and it doesn't work for me. The line just stays in the same place.

@Computergeek The problem is that when i move my mouse it does not act as an end point, it just fly's off the screen. Probably because of the mouse coordinates being off.

Thanks
Josh
The problem is that your xPosg and yPosg are ints. They have to be able to represent any value in range (-1; 1) so they have to be floats.
Also, I just tested it, and, as I expected you need to invert your Y axis. (yPosg = -(2.0*yPos/1040 -1);)

By screen_width/height I did mean width and height of your window. However, if you try your fixed code now, you'll notice that line doesn't end exactly where it should. This is because 1040 is not the width of the client area but the width of the whole window.
Firstly, you can fix that with AdjustWindowRect. example:
1
2
3
Rect RECT r = {0, 0, 1280, 1040};
AdjustWindowRect(&r, WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE, 0);
//then create the window. use r.right-r.left and r.botom-r.top for width and height 
.
Another problem is resizing. You need to create two variables for width and height. You have to handle WM_SIZE message (width = LOWORD(lParam), height = HIWORD(lParam) ).

edit: it's RECT, not Rect.
Last edited on
closed account (DSvMDjzh)
Thanks for the help, I did end up inverting the y axis. I modified your equation for xPosg and yPosg
1
2
xPosg = ConvertAxes(xPos,640);
yPosg = -1*ConvertAxes(yPos,512);

and then
1
2
3
4
5
6
7
float ConvertAxes(float Mouse,float MouseMax){

	float out=1;

		out=(Mouse/MouseMax)-1;

	return out;


It works pretty well. I will try the AdjustWindowRect. but i think i will mark this as solved.

Thanks very much for the help Hamsterman/Computergeek.

Josh


EDIT:
Where would I put the AdjustWindowRect. ? I'm not sure as to where to put it.
Last edited on
Put AdjustWindowRect right before CreateWindow. Use r.right-r.left and r.botom-r.top for width and height.
I suggest handling WM_SIZE however. You wouldn't want to break your program every time you resize a window..
Oh. I just noticed that your window isn't resizable..
closed account (DSvMDjzh)
Thanks, it works!

Josh
Topic archived. No new replies allowed.