Related
i was trying to create a win32 that could handle openGl ( the new version). It doesnt seem to be mutch info about win32/opengl(new version, most examples are in the old version ) on the net.
The few info that i found lead me to this code. But it doesnt display the square.
Does any one know if this is the proper way to do it, and if so what is wrong with it(it doesnt display square).
Ps. i know that the part of the vbo, vao ,shader.. are working cause i already did that with sdl.
Thank a lot.... :)
Here is the Code:
#include <iostream>
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
#include <glew.h>
#include <wglew.h>
using namespace std;
void display(){
// display square
}
bool progRun = false;
//-------------------------------------------------------------------
//#####################################################################
//-------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int CALLBACK WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
){
WNDCLASSEX wcex;
///////////////////////////LOAD GLEW///////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS ;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = NULL;
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL,"RegisterClassEx","ERROR",MB_OK|MB_ICONSTOP);
return 0;
}
HWND hWnd = CreateWindow(
szWindowClass,
szTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
500, 500,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
{
MessageBox(NULL,"hWnd","ERROR",MB_OK|MB_ICONSTOP);
return -1;
}
HDC hdc = GetDC(hWnd);
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nSize= sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 32;
pfd.iLayerType = PFD_MAIN_PLANE;
int pf = ChoosePixelFormat(hdc, &pfd);
if(pf == 0){
MessageBox(NULL,"pf == 0","ERROR",MB_OK|MB_ICONSTOP);
return -1;
}
if(SetPixelFormat(hdc, pf, &pfd) == false){
MessageBox(NULL,"SetPixelFormat","ERROR",MB_OK|MB_ICONSTOP);
return -1;
}
DescribePixelFormat(hdc, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
HGLRC hrc = wglCreateContext(hdc);
wglMakeCurrent(hdc, hrc);
glewExperimental = true;
if(glewInit() != GLEW_OK){
MessageBox(NULL, "Couldn't initialize GLEW!", "Fatal Error", MB_ICONERROR);
}
wglMakeCurrent(NULL, NULL);
ReleaseDC(hWnd, hdc);
wglDeleteContext(hrc);
DestroyWindow(hWnd);
///////////////////////////////TO_CREATE A OPENGL CONTEXT WITH LATER VERSION///////////////////////////////////////
//////////////////////////////////////////////////////////////////////
#define iMajorVersion 3
#define iMinorVersion 1
hWnd = CreateWindow(
szWindowClass,
szTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
500, 500,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
{
MessageBox(NULL,"hWnd","ERROR",MB_OK|MB_ICONSTOP);
return -1;
}
hdc = GetDC(hWnd);
bool bError = false;
if(iMajorVersion <= 2)
{
cout << "version 2" <<endl;
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 32;
pfd.iLayerType = PFD_MAIN_PLANE;
pf = ChoosePixelFormat(hdc, &pfd);
if (pf == 0){
MessageBox(NULL,"pf == 0","ERROR",MB_OK|MB_ICONSTOP);
return false;
}
if(!SetPixelFormat(hdc, pf, &pfd)){
MessageBox(NULL,"SetPixelFormat 1","ERROR",MB_OK|MB_ICONSTOP);
return false;
}
// Create the old style context (OpenGL 2.1 and before)
hrc = wglCreateContext(hdc);
if(hrc)wglMakeCurrent(hdc, hrc);
else bError = true;
}
else if(WGLEW_ARB_create_context && WGLEW_ARB_pixel_format)
{
cout << "version 3" <<endl;
const int iPixelFormatAttribList[] =
{
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
WGL_COLOR_BITS_ARB, 32,
WGL_DEPTH_BITS_ARB, 24,
WGL_STENCIL_BITS_ARB, 8,
0 // End of attributes list
};
int iContextAttribs[] =
{
WGL_CONTEXT_MAJOR_VERSION_ARB, iMajorVersion,
WGL_CONTEXT_MINOR_VERSION_ARB, iMinorVersion,
WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
0 // End of attributes list
};
int iNumFormats;
if(!wglChoosePixelFormatARB(hdc, iPixelFormatAttribList, NULL, 1, &pf, (UINT*)&iNumFormats)){
MessageBox(NULL,"wglChoosePixelFormatARB","ERROR",MB_OK|MB_ICONSTOP);
return 0;
}
// PFD seems to be only redundant parameter now
if(!SetPixelFormat(hdc, pf, &pfd)){
MessageBox(NULL,"SetPixelFormat 2","ERROR",MB_OK|MB_ICONSTOP);
return false;
}
hrc = wglCreateContextAttribsARB(hdc, 0, iContextAttribs);
// If everything went OK
if(hrc) wglMakeCurrent(hdc, hrc);
else bError = true;
//glewInit();
}else{
bError = true;
}
if(bError)
{
// Generate error messages
char sErrorMessage[255], sErrorTitle[255];
sprintf(sErrorMessage, "OpenGL %d.%d is not supported! Please download latest GPU drivers!", iMajorVersion, iMinorVersion);
sprintf(sErrorTitle, "OpenGL %d.%d Not Supported", iMajorVersion, iMinorVersion);
MessageBox(hWnd, sErrorMessage, sErrorTitle, MB_ICONINFORMATION);
return false;
}
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
MSG msg;
progRun = true;
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//-----------Setup shader and objects
setupShader();
setupObject();
//-------
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL);
glClearColor(1,0,0,1);
while(progRun){
if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
glClear(GL_COLOR_BUFFER_BIT);
display();
SwapBuffers(hdc);
}
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
switch (message){
case WM_ERASEBKGND:
display();
break;
case WM_PAINT:
BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_SIZE:
glViewport(0, 0, LOWORD(lParam), HIWORD(lParam));
break;
case WM_DESTROY:
PostQuitMessage(0);
progRun = false;
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
If you use wglCreateContext then you get old context (<= 2.1).
You need wglCreateContextAttribsARB instead. But this first you need to get a pointer to this function, which requires using a context.
So:
Create a normal, old context, and set it current. Any pixelformat is
valid.
Get the pointers to wglCreateContextAttribsARB (and perhaps also for wglChoosePixelFormatARB), by using
wglGetProcAddress. Now you can delete the old context.
Set the pixelformat you wish and the context attributes you wish.
Create the context by that pointer.
Useful links from the wiki OpenGL are here and here and here
I have a callback function:
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
if(msg == WM_DESTROY || msg == WM_CLOSE) {
std::cout << "Close or get DESTROYED!\n";
}
if(g_mApp)
return g_mApp->MsgProc(hwnd, msg, wParam, lParam);
else
return DefWindowProc(hwnd, msg, wParam, lParam);
}
However, "Close or get Destroyed" isn't printed when I click on the X button or press Alt+F4. Infact, I am unable to move the window by the mouse!
Some other functions:
int GLApp::run() {
__int64 prevTime = 0;
QueryPerformanceCounter((LARGE_INTEGER*)&prevTime);
__int64 countsPerSec = 0;
QueryPerformanceCounter((LARGE_INTEGER*)&countsPerSec);
float secondsPerCount = 1.0f / countsPerSec;
MSG msg = {0};
while(msg.message != WM_QUIT) {
if(!PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else {
__int64 curTime = 0;
QueryPerformanceCounter((LARGE_INTEGER*)&curTime);
float deltaTime = (curTime - prevTime) * secondsPerCount;
update(deltaTime);
render();
calculateFPS(deltaTime);
prevTime = curTime;
}
}
shutdown();
return static_cast<int>(msg.wParam);
}
bool GLApp::initWindow() {
WNDCLASSEX wcex;
ZeroMemory(&wcex, sizeof(WNDCLASSEX));
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.hInstance = m_hAppInstance;
wcex.lpfnWndProc = MainWndProc;
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
wcex.lpszClassName = "GLAPPWNDCLASS";
wcex.lpszMenuName = NULL;
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wcex)) {
return outErrorMessage("Failed to register GLAPPWNDCLASS");
}
// ADJUST WINDOW RECT FOR REQUESTED CLIENT SIZE
RECT r;
r.left = r.top = 0;
r.right = m_ClientWidth;
r.bottom = m_ClientHeight;
AdjustWindowRect(&r, m_WindowStyle, FALSE);
int width = r.right - r.left;
int height = r.bottom - r.top;
int x = GetSystemMetrics(SM_CXSCREEN)/2 - width / 2;
int y = GetSystemMetrics(SM_CYSCREEN)/2 - height / 2;
m_hAppWnd = CreateWindow("GLAPPWNDCLASS", m_AppTitle, m_WindowStyle, x, y, width, height, NULL, NULL, m_hAppInstance, NULL);
if(!m_hAppWnd) return outErrorMessage("Failed to create window from GLAPPWNDCLASS");
ShowWindow(m_hAppWnd, SW_SHOW);
return true;
}
g_mApp is my own object for implementing the window. initWindow() and run() are called only once respectively. The full class if you will:
#include "GLApp.h"
#include <iostream>
namespace {
GLApp* g_mApp = NULL;
}
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
if(msg == WM_DESTROY || msg == WM_CLOSE) {
std::cout << "Close or get DESTROYED!\n";
}
if(g_mApp)
return g_mApp->MsgProc(hwnd, msg, wParam, lParam);
else
return DefWindowProc(hwnd, msg, wParam, lParam);
}
GLApp::GLApp(void)
{
}
GLApp::GLApp(HINSTANCE hInstance) {
m_hAppInstance = hInstance;
m_hAppWnd = NULL;
m_hDevContext = NULL;
m_hGLRenderContext = NULL;
m_ClientWidth = 800;
m_ClientHeight = 600;
m_AppTitle = "OpenGL Application";
m_WindowStyle = WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX;
m_FPS = 0.0f;
g_mApp = this;
}
GLApp::~GLApp()
{
}
int GLApp::run() {
__int64 prevTime = 0;
QueryPerformanceCounter((LARGE_INTEGER*)&prevTime);
__int64 countsPerSec = 0;
QueryPerformanceCounter((LARGE_INTEGER*)&countsPerSec);
float secondsPerCount = 1.0f / countsPerSec;
MSG msg = {0};
while(msg.message != WM_QUIT) {
if(!PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else {
__int64 curTime = 0;
QueryPerformanceCounter((LARGE_INTEGER*)&curTime);
float deltaTime = (curTime - prevTime) * secondsPerCount;
update(deltaTime);
render();
calculateFPS(deltaTime);
prevTime = curTime;
}
}
shutdown();
return static_cast<int>(msg.wParam);
}
bool GLApp::init() {
return initWindow() && initGL();
}
bool GLApp::initWindow() {
WNDCLASSEX wcex;
ZeroMemory(&wcex, sizeof(WNDCLASSEX));
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.hInstance = m_hAppInstance;
wcex.lpfnWndProc = MainWndProc;
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
wcex.lpszClassName = "GLAPPWNDCLASS";
wcex.lpszMenuName = NULL;
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wcex)) {
return outErrorMessage("Failed to register GLAPPWNDCLASS");
}
// ADJUST WINDOW RECT FOR REQUESTED CLIENT SIZE
RECT r;
r.left = r.top = 0;
r.right = m_ClientWidth;
r.bottom = m_ClientHeight;
AdjustWindowRect(&r, m_WindowStyle, FALSE);
int width = r.right - r.left;
int height = r.bottom - r.top;
int x = GetSystemMetrics(SM_CXSCREEN)/2 - width / 2;
int y = GetSystemMetrics(SM_CYSCREEN)/2 - height / 2;
m_hAppWnd = CreateWindow("GLAPPWNDCLASS", m_AppTitle, m_WindowStyle, x, y, width, height, NULL, NULL, m_hAppInstance, NULL);
if(!m_hAppWnd) return outErrorMessage("Failed to create window from GLAPPWNDCLASS");
ShowWindow(m_hAppWnd, SW_SHOW);
return true;
}
bool GLApp::initGL() {
// CREATE OUR DEVICE CONTEXT
m_hDevContext = GetDC(m_hAppWnd);
// CREATE PIXEL FORMAT DESCRIPTOR
PIXELFORMATDESCRIPTOR pfd;
ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 24;
pfd.cStencilBits = 8;
int format = ChoosePixelFormat(m_hDevContext, &pfd);
if(!SetPixelFormat(m_hDevContext, format, &pfd)) {
return outErrorMessage("Failed to set pixel format");
}
// CREATE RENDER CONTEXT
m_hGLRenderContext = wglCreateContext(m_hDevContext);
if(!wglMakeCurrent(m_hDevContext, m_hGLRenderContext)) {
return outErrorMessage("Failed to create and activate render context");
}
// INITIALIZE GLEW
if(glewInit() != GLEW_OK) {
return outErrorMessage("Failed to initialize GLEW");
}
return true;
}
LRESULT GLApp::MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch(msg) {
case WM_CLOSE: {
DestroyWindow(hwnd);
return 0;
}
case WM_DESTROY: {
PostQuitMessage(0);
return 0;
}
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
}
void GLApp::calculateFPS(float dt) {
}
void GLApp::shutdown() {
wglMakeCurrent(NULL, NULL);
wglDeleteContext(m_hGLRenderContext);
ReleaseDC(m_hAppWnd, m_hDevContext);
}
This is how it is implemented:
#include "GLApp.h"
#include <iostream>
class TestApp : public GLApp {
public:
TestApp(HINSTANCE hInstance);
~TestApp();
// OVERRIDES
bool init() override;
void update(float dt) override;
void render() override;
LRESULT MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) override;
};
TestApp::TestApp(HINSTANCE hInstance) : GLApp(hInstance) {
}
TestApp::~TestApp() {}
bool TestApp::init() {
return GLApp::init();
}
void TestApp::update(float dt) {
}
void TestApp::render() {
}
LRESULT TestApp::MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch(msg) {
default:
return GLApp::MsgProc(hwnd, msg, wParam, lParam);
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPSTR lpCmdLine, int nCmdShow) {
TestApp app(hInstance);
if(!app.init()) {
return 1;
}
return app.run();
}
bool outErrorMessage(const char* message) {
MessageBox(NULL, message, NULL, MB_OK);
return false;
}
!PeekMessage is wrong, if it returns non-zero you got a message you need to handle.
OS: Windows 7, 64 bit
Visual Studio 2010, debug, 32 bit
I'm trying out a simple Windows program to start working with openGL: all the program should do is clear the color buffer with glClear(GL_COLOR_BUFFER_BIT).
In the tutorials I found on the web, I find that people are creating and setting the openGL context during the creation of the window (and thus during the treatment of the WM_CREATE message). Somehow, I find that this doesn't work for my code and I don't seem to be able to figure it out. So if anyone could point me in the right direction.
Please find hereafter the code how I expect that it should work based on tutorials:
#include <windows.h>
#include <GL\glew.h>
#include <GL\wglew.h>
#include "Application.h"
HWND ghMainWnd = 0;
bool InitWindowsApp(HINSTANCE instanceHandle, int show);
int Run();
LRESULT CALLBACK
WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
HDC hDC;
HGLRC hGLRC;
HPALETTE hPalette;
void SetupPixelFormat()
{
PIXELFORMATDESCRIPTOR pfd = {};
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cAlphaBits = 8;
pfd.cDepthBits = 32;
pfd.iLayerType = PFD_MAIN_PLANE;
int pixelFormat = ChoosePixelFormat(hDC, &pfd);
if(pixelFormat == 0)
{
MessageBox(ghMainWnd, L"ChoosePixelFormat() failed", L"Error", MB_ICONERROR | MB_OK);
exit(1);
}
if(!SetPixelFormat(hDC, pixelFormat, &pfd))
{
MessageBox(ghMainWnd, L"SetPixelFormat() failed", L"Error", MB_ICONERROR | MB_OK);
exit(1);
}
}
int WINAPI
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nShowCmd)
{
if(!InitWindowsApp(hInstance, nShowCmd))
return 0;
return Run();
}
bool InitWindowsApp(HINSTANCE instanceHandle, int show)
{
WNDCLASS wc;
wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = instanceHandle;
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = 0;
wc.lpszClassName = L"BasicWndClass";
if(!RegisterClass(&wc))
{
MessageBox(0, L"RegisterClass failed", 0, 0);
return false;
}
ghMainWnd = CreateWindow(
L"BasicWndClass",
L"BasicWindowsApp",
WS_OVERLAPPEDWINDOW,
0,
0,
600,
600,
0,
0,
instanceHandle,
0);
if(ghMainWnd == 0)
{
MessageBox(0, L"CreateWindow failed", 0, 0);
return false;
}
ShowWindow(ghMainWnd, show);
UpdateWindow(ghMainWnd);
return true;
}
int Run()
{
MSG msg = {0};
Application *pApp = new Application();
pApp->Init();
while(msg.message != WM_QUIT)
{
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
//Do Other stuff
pApp->Draw();
SwapBuffers(hDC);
}
}
if(pApp)
{
delete pApp;
pApp = nullptr;
}
return (int)msg.wParam;
}
LRESULT CALLBACK
WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
hDC = GetDC(ghMainWnd);
SetupPixelFormat();
hGLRC = wglCreateContext(hDC);
if(!hGLRC)
{
MessageBox(ghMainWnd, L"wglCreateContext() failed", L"Error", MB_ICONERROR | MB_OK);
exit(1);
}
if(!wglMakeCurrent(hDC, hGLRC))
{
MessageBox(ghMainWnd, L"wglMakeCurrent() failed", L"Error", MB_ICONERROR | MB_OK);
exit(1);
}
glViewport(0, 0, 600, 600);
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
return 0;
case WM_LBUTTONDOWN:
return 0;
case WM_KEYDOWN:
if(wParam == VK_ESCAPE)
DestroyWindow(ghMainWnd);
return 0;
case WM_DESTROY:
if(hGLRC)
{
wglMakeCurrent(nullptr, nullptr);
wglDeleteContext(hGLRC);
}
ReleaseDC(ghMainWnd, hDC);
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
Below, I found a "hack" to make it work: I basically move the opengl context creation into the InitWindowsApp() function... But why does the code above doesn't work?
#include <windows.h>
#include <GL\glew.h>
#include <GL\wglew.h>
#include "Application.h"
HWND ghMainWnd = 0;
bool InitWindowsApp(HINSTANCE instanceHandle, int show);
int Run();
LRESULT CALLBACK
WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
HDC hDC;
HGLRC hGLRC;
HPALETTE hPalette;
void SetupPixelFormat()
{
PIXELFORMATDESCRIPTOR pfd = {};
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cAlphaBits = 8;
pfd.cDepthBits = 32;
pfd.iLayerType = PFD_MAIN_PLANE;
int pixelFormat = ChoosePixelFormat(hDC, &pfd);
if(pixelFormat == 0)
{
MessageBox(ghMainWnd, L"ChoosePixelFormat() failed", L"Error", MB_ICONERROR | MB_OK);
exit(1);
}
if(!SetPixelFormat(hDC, pixelFormat, &pfd))
{
MessageBox(ghMainWnd, L"SetPixelFormat() failed", L"Error", MB_ICONERROR | MB_OK);
exit(1);
}
}
int WINAPI
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nShowCmd)
{
if(!InitWindowsApp(hInstance, nShowCmd))
return 0;
return Run();
}
bool InitWindowsApp(HINSTANCE instanceHandle, int show)
{
WNDCLASS wc;
wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = instanceHandle;
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = 0;
wc.lpszClassName = L"BasicWndClass";
if(!RegisterClass(&wc))
{
MessageBox(0, L"RegisterClass failed", 0, 0);
return false;
}
ghMainWnd = CreateWindow(
L"BasicWndClass",
L"BasicWindowsApp",
WS_OVERLAPPEDWINDOW,
0,
0,
600,
600,
0,
0,
instanceHandle,
0);
if(ghMainWnd == 0)
{
MessageBox(0, L"CreateWindow failed", 0, 0);
return false;
}
ShowWindow(ghMainWnd, show);
UpdateWindow(ghMainWnd);
hDC = GetDC(ghMainWnd);
SetupPixelFormat();
hGLRC = wglCreateContext(hDC);
if(!hGLRC)
{
MessageBox(ghMainWnd, L"wglCreateContext() failed", L"Error", MB_ICONERROR | MB_OK);
exit(1);
}
if(!wglMakeCurrent(hDC, hGLRC))
{
MessageBox(ghMainWnd, L"wglMakeCurrent() failed", L"Error", MB_ICONERROR | MB_OK);
exit(1);
}
glViewport(0, 0, 600, 600);
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
return true;
}
int Run()
{
MSG msg = {0};
Application *pApp = new Application();
pApp->Init();
while(msg.message != WM_QUIT)
{
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
//Do Other stuff
pApp->Draw();
SwapBuffers(hDC);
}
}
if(pApp)
{
delete pApp;
pApp = nullptr;
}
return (int)msg.wParam;
}
LRESULT CALLBACK
WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
return 0;
case WM_LBUTTONDOWN:
return 0;
case WM_KEYDOWN:
if(wParam == VK_ESCAPE)
DestroyWindow(ghMainWnd);
return 0;
case WM_DESTROY:
if(hGLRC)
{
wglMakeCurrent(nullptr, nullptr);
wglDeleteContext(hGLRC);
}
ReleaseDC(ghMainWnd, hDC);
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
When WM_CREATE arrives, your ghMainWnd is still NULL (the message is sent before the CreateWindow call returns). Instead, use the hWnd parameter of the message in your GetDC call.
Hi I am currently working on a project where we are creating a UDP server to communicate with a KUKA robot. We are able to establish the connection with the robot and exchange the data back and forth but when an event occurs such as the robot faulting out due to motor over torque. So to detect this fault we have added a timeout to the code so that the main dialog box will close and reopen so that all the variables will be reinitialized and we can set the connection to reestablish.
Heres the server code:
#include "stdafx.h"
#include "HapticRobot.h"
#include "CMaths.h"
using namespace chai3d;
#include <winsock.h>
using namespace std;
#pragma comment(lib, "Ws2.lib")
#include <fstream>
#include <string>
#include <sstream>
DWORD WINAPI DoGravity(LPVOID lpParameter);
#define REFRESH_INTERVAL 0 // sec
const int kBufferSize = 1024;
int nTempHold;
extern HapticDevice hd;
extern HWND g_hWndHapticBox;
extern bool bRobotInMotion, bRobotConnectInit, bRobotConnected;
extern Handles hc;
bool err;
std::string stSend, stSendXML, stLine;
std::string stRobotStatus , stAppend;
TCHAR *chRobotStatus;
//variables for timeout
fd_set fds;
int n;
struct timeval tv;
//// Prototypes ////////////////////////////////////////////////////////
SOCKET SetUpListener(const char* pcAddress, int nPort);
bool EchoIncomingPackets(SOCKET sd);
//// DoWinsock /////////////////////////////////////////////////////////
// The module's driver function -- we just call other functions and
// interpret their results.
int DoWinsock(const char* pcAddress, int nPort)
{
int nRetval = 0;
ifstream inFile("HardDisk/ExternalData.xml");
if (inFile.is_open())
{
while ( inFile.good() )
{
getline ( inFile, stLine);
stSendXML.append(stLine);
}
inFile.close();
}
SendDlgItemMessage(g_hWndHapticBox, IDC_LIST_Server, LB_INSERTSTRING, 0, (LPARAM)L"Establishing the listener...");
SOCKET ListeningSocket = SetUpListener(pcAddress, htons(nPort));
SendDlgItemMessage(g_hWndHapticBox, IDC_LIST_Server, LB_INSERTSTRING, 0, (LPARAM)L"Waiting for connections...");
bRobotConnectInit = true;
SetDlgItemText(g_hWndHapticBox, IDC_STATIC_RobotStatus, _T("Waiting for robot"));
while (1)
{
EchoIncomingPackets(ListeningSocket);
bRobotConnected = false;
bRobotConnectInit = true;
SendDlgItemMessage(g_hWndHapticBox, IDC_LIST_Server, LB_INSERTSTRING, 0, (LPARAM)L"Acceptor restarting...");
}
}
//// SetUpListener /////////////////////////////////////////////////////
// Sets up a listener on the given interface and port, returning the
// listening socket if successful; if not, returns INVALID_SOCKET.
SOCKET SetUpListener(const char* pcAddress, int nPort)
{
u_long nInterfaceAddr = inet_addr(pcAddress);
if (nInterfaceAddr != INADDR_NONE)
{
SOCKET sd = socket(AF_INET, SOCK_DGRAM, 0);
sockaddr_in sinInterface;
sinInterface.sin_family = AF_INET;
sinInterface.sin_addr.s_addr = nInterfaceAddr;
sinInterface.sin_port = nPort;
if (bind(sd, (sockaddr*)&sinInterface,
sizeof(sockaddr_in)) != SOCKET_ERROR)
{
return sd;
}
}
return INVALID_SOCKET;
}
//// EchoIncomingPackets ///////////////////////////////////////////////
// Bounces any incoming packets back to the client. We return false
// on errors, or true if the client closed the socket normally.
bool EchoIncomingPackets(SOCKET sd)
{
// Read data from client
std::string stReceive;
std::string stIPOC;
std::wstring stTime;
int nStartPos, nEndPos;
char acReadBuffer[kBufferSize], acWriteBuffer[512];
int nReadBytes;
struct sockaddr_in clientAddr;
int sockAddrSize = sizeof(struct sockaddr_in);
//declarations for the low pass filter
int CURRENT_VALUE = 2;
double T = .004, w_co, OMEGA_co, f_co;
hd.bFirstRunRobot = true;
do
{
//This will be to timeout the socket connection
FD_ZERO(&fds);
FD_SET(sd, &fds);
tv.tv_sec = 5;
tv.tv_usec = 0;
n = select (sd, &fds, NULL, NULL, &tv );
if (n == 0)
{
PostMessage(g_hWndHapticBox,WM_CLOSE, 0, 0);
Sleep(5000);
PostMessage(g_hWndHapticBox, WM_INITDIALOG, 0, 0);
Sleep(1000);
//printf("Timeout..\n");
//HapticBox(HWND, UINT, WPARAM, LPARAM);
//return 0;
}
else if (n == -1)
{
printf("Error..\n");
return 1;
}
// end timeout
nReadBytes = recvfrom(sd, acReadBuffer, sizeof(acReadBuffer), 0, (struct sockaddr*)&clientAddr, &sockAddrSize);
//nReadBytes = recvfrom(sd, acReadBuffer, sizeof(acReadBuffer), MSG_PEEK, (struct sockaddr*)&clientAddr, &sockAddrSize);
//if (nReadBytes == SOCKET_ERROR)
//{
// SetDlgItemText(g_hWndHapticBox, IDC_STATIC_RobotStatus, _T("ERROR"));
//}
if (nReadBytes < 0 || nReadBytes == 0)
{
SetDlgItemText(g_hWndHapticBox, IDC_STATIC_RobotStatus, _T("ERROR 1"));
return true;
}
if (nReadBytes > 0)
{
if (bRobotConnectInit)
{
bRobotConnectInit = false;
bRobotConnected = true;
SetDlgItemText(g_hWndHapticBox, IDC_STATIC_RobotStatus, _T("Connected to Robot"));
}
}
stSend = stSendXML;
stReceive = acReadBuffer;
nStartPos = stReceive.find ("<IPOC>") + 6;
nEndPos = stReceive.find ("</IPOC>");
stIPOC = stReceive.substr (nStartPos, nEndPos - nStartPos);
nStartPos = stSend.find ("<IPOC>") + 6;
nEndPos = stSend.find ("</IPOC>");
stSend.replace(nStartPos, nEndPos - nStartPos, stIPOC);
//Raw sensor data
nStartPos = stReceive.find ("RFx=") + 5;
nEndPos = stReceive.find ("RFy=") - 2;
hd.stRFx = stReceive.substr (nStartPos, nEndPos - nStartPos);
hd.szRFx = hd.stRFx.c_str();
hd.RFx = strtod(hd.szRFx, NULL);
hd.RFx = hd.RFx * 0.22;
nStartPos = stReceive.find ("RFy=") + 5;
nEndPos = stReceive.find ("RFz=") - 2;
hd.stRFy = stReceive.substr (nStartPos, nEndPos - nStartPos);
hd.szRFy = hd.stRFy.c_str();
hd.RFy = strtod(hd.szRFy, NULL);
hd.RFy = hd.RFy * 0.22;
**//...more XML stuff...//**
//data the is to be sent to the robot
if (hd.FirstTimePosition)
{
hd.RobotXStartPosition = hd.RobotXPosition;
hd.RobotYStartPosition = hd.RobotYPosition;
hd.RobotZStartPosition = hd.RobotZPosition;
hd.FirstTimePosition = false;
}
if(hd.LinearScale == 4)
{
f_co = 0.5;
}
else if (hd.LinearScale == 3)
{
f_co = 0.5;
}
else if (hd.LinearScale == 2)
{
f_co = 1;
}
else if (hd.LinearScale == 1)
{
f_co = 2;
}
else if (hd.LinearScale == 0.5)
{
f_co = 2;
}
else
{
f_co = 0.5;
}
if (hd.Fz < hd.MaxForcePos)
{
hd.ForceLimitPosZ = false;
}
if (hd.Fz > hd.MaxForceNeg)
{
hd.ForceLimitNegZ = false;
}
if (hd.Fz > hd.MaxForcePos || hd.ForceLimitPosZ)
{
if (!hd.ForceLimitPosZ)
{
hd.CurrentZtoRobotPosition = hd.ZtoRobot;
}
if (hd.CurrentZtoRobotPosition >= hd.ZtoRobot)
{
hd.NewZtoRobot = hd.PreviousZtoRobot;
hd.ForceLimitPosZ = true;
}
else
{
hd.ForceLimitPosZ = false;
}
}
if (hd.ForceLimitPosZ)
{
hd.ForceZtoRobot = hd.NewZtoRobot;
}
else
{
hd.ForceZtoRobot = hd.ZtoRobot;
}
w_co = f_co * C_TWO_PI;
OMEGA_co = (2/T) * cTanRad((w_co * T) / 2);
hd.raw_x[CURRENT_VALUE] = hd.XtoRobot;
hd.raw_y[CURRENT_VALUE] = hd.YtoRobot;
hd.raw_z[CURRENT_VALUE] = hd.ForceZtoRobot;
hd.filtered_x[CURRENT_VALUE] = (pow(((OMEGA_co) / ((2 / T) + OMEGA_co)), 2)) *
((hd.raw_x[CURRENT_VALUE]) + (2 * hd.raw_x[CURRENT_VALUE - 1] + hd.raw_x[CURRENT_VALUE - 2]))
- (((2 * (OMEGA_co - (2 / T))) / ((2 / T) + OMEGA_co)) * hd.filtered_x[CURRENT_VALUE - 1])
- ((pow(((OMEGA_co - (2 / T)) / ((2 / T) + OMEGA_co)),2)) * hd.filtered_x[CURRENT_VALUE - 2]);
**//more digital filter stuff//**
hd.raw_x[CURRENT_VALUE - 2] = hd.raw_x[CURRENT_VALUE - 1];
hd.raw_y[CURRENT_VALUE - 2] = hd.raw_y[CURRENT_VALUE - 1];
hd.raw_z[CURRENT_VALUE - 2] = hd.raw_z[CURRENT_VALUE - 1];
hd.raw_x[CURRENT_VALUE - 1] = hd.raw_x[CURRENT_VALUE];
hd.raw_y[CURRENT_VALUE - 1] = hd.raw_y[CURRENT_VALUE];
hd.raw_z[CURRENT_VALUE - 1] = hd.raw_z[CURRENT_VALUE];
hd.filtered_x[CURRENT_VALUE - 2] = hd.filtered_x[CURRENT_VALUE - 1];
hd.filtered_y[CURRENT_VALUE - 2] = hd.filtered_y[CURRENT_VALUE - 1];
hd.filtered_z[CURRENT_VALUE - 2] = hd.filtered_z[CURRENT_VALUE - 1];
hd.filtered_x[CURRENT_VALUE - 1] = hd.filtered_x[CURRENT_VALUE];
hd.filtered_y[CURRENT_VALUE - 1] = hd.filtered_y[CURRENT_VALUE];
hd.filtered_z[CURRENT_VALUE - 1] = hd.filtered_z[CURRENT_VALUE];
hd.stXtoRobot = dtostr(hd.filtered_x[CURRENT_VALUE]);
nStartPos = stSend.find ("X=") + 3;
stSend.replace(nStartPos, 6, hd.stXtoRobot);
hd.stYtoRobot = dtostr(hd.filtered_y[CURRENT_VALUE]);
nStartPos = stSend.find ("Y=") + 3;
stSend.replace(nStartPos, 6, hd.stYtoRobot);
hd.stZtoRobot = dtostr(hd.filtered_z[CURRENT_VALUE]);
nStartPos = stSend.find ("Z=") + 3;
stSend.replace(nStartPos, 6, hd.stZtoRobot);
if (hd.ForceLimitPosZ)
{
hd.PreviousZtoRobot = hd.NewZtoRobot;
}
else
{
hd.PreviousZtoRobot = hd.ZtoRobot;
}
strcpy( static_cast<char*>( &acWriteBuffer[0] ), stSend.c_str() );
if (nReadBytes > 0)
{
int nSentBytes = 0;
int SendLength = strlen(acWriteBuffer);
while (nSentBytes < SendLength)
{
int nTemp = sendto(sd, acWriteBuffer, SendLength, 0, (const sockaddr*)&clientAddr, sockAddrSize);
nTempHold = nTemp;
if (nTemp > 0)
{
nSentBytes += nTemp;
}
else if (nTemp == SOCKET_ERROR)
{
return false;
}
else
{
// Client closed connection before we could reply to
// all the data it sent, so bomb out early.
SendDlgItemMessage(g_hWndHapticBox, IDC_LIST_Server, LB_INSERTSTRING, 0, (LPARAM)L"Peer unexpectedly dropped connection!");
return true;
}
}
}
else if (nReadBytes == SOCKET_ERROR)
{
return false;
}
hd.bFirstRunRobot = false;
}while (nReadBytes != 0);
SendDlgItemMessage(g_hWndHapticBox, IDC_LIST_Server, LB_INSERTSTRING, 0, (LPARAM)L"Connection closed by peer.");
bRobotConnected = false;
bRobotConnectInit = true;
SetDlgItemText(g_hWndHapticBox, IDC_STATIC_RobotStatus, _T("Waiting for robot"));
SetDlgItemText(g_hWndHapticBox, IDC_STATIC_RobotInMotion, _T("Robot not in motion"));
return true;
//}
}
And here is the code for the GUI:
// HapticRobot.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "HapticRobot.h"
#include <sstream>
#include <string>
using namespace std;
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE g_hInst; // current instance
HWND g_hWndCommandBar; // command bar handle
HWND g_hWndHapticBox; // haptic dialog handle
bool bRobotInMotion, bRobotConnectInit, bRobotConnected;
extern HapticDevice hd;
HDC hdc;
Handles hc;
DWORD WINAPI DoGravity(LPVOID lpParameter);
DWORD WINAPI DoConnectRobot(LPVOID lpParameter);
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE, LPTSTR);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK HapticBox(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
// Perform application initialization:
if (!InitInstance(hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable;
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_HAPTICROBOT));
DialogBox(hInstance, (LPCTSTR)IDD_HAPTIC, NULL, HapticBox);
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
ATOM MyRegisterClass(HINSTANCE hInstance, LPTSTR szWindowClass)
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_HAPTICROBOT));
wc.hCursor = 0;
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = 0;
wc.lpszClassName = szWindowClass;
return RegisterClass(&wc);
}
//FUNCTION: InitInstance(HINSTANCE, int)
//PURPOSE: Saves instance handle and creates main window
//COMMENTS:
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
TCHAR szTitle[MAX_LOADSTRING]; // title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // main window class name
g_hInst = hInstance; // Store instance handle in our global variable
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_HAPTICROBOT, szWindowClass, MAX_LOADSTRING);
if (!MyRegisterClass(hInstance, szWindowClass))
{
return FALSE;
}
hWnd = CreateWindow(szWindowClass, szTitle, WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
if (g_hWndCommandBar)
{
CommandBar_Show(g_hWndCommandBar, TRUE);
}
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_HELP_ABOUT:
DialogBox(g_hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, About);
break;
case IDM_FILE_EXIT:
dhdClose ();
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_CREATE:
g_hWndCommandBar = CommandBar_Create(g_hInst, hWnd, 1);
CommandBar_InsertMenubar(g_hWndCommandBar, g_hInst, IDR_MENU, 0);
CommandBar_AddAdornments(g_hWndCommandBar, 0, 0);
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
dhdClose ();
CommandBar_Destroy(g_hWndCommandBar);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
RECT rectChild, rectParent;
int DlgWidth, DlgHeight; // dialog width and height in pixel units
int NewPosX, NewPosY;
// trying to center the About dialog
if (GetWindowRect(hDlg, &rectChild))
{
GetClientRect(GetParent(hDlg), &rectParent);
DlgWidth = rectChild.right - rectChild.left;
DlgHeight = rectChild.bottom - rectChild.top ;
NewPosX = (rectParent.right - rectParent.left - DlgWidth) / 2;
NewPosY = (rectParent.bottom - rectParent.top - DlgHeight) / 2;
// if the About box is larger than the physical screen
if (NewPosX < 0) NewPosX = 0;
if (NewPosY < 0) NewPosY = 0;
SetWindowPos(hDlg, 0, NewPosX, NewPosY,
0, 0, SWP_NOZORDER | SWP_NOSIZE);
}
return (INT_PTR)TRUE;
case WM_COMMAND:
if ((LOWORD(wParam) == IDOK) || (LOWORD(wParam) == IDCANCEL))
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
case WM_CLOSE:
EndDialog(hDlg, message);
return TRUE;
}
return (INT_PTR)FALSE;
}
// Message handler for haptic box.
BOOL CALLBACK HapticBox(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
SetWindowPos(hDlg, 0, 130, 200,
0, 0, SWP_NOZORDER | SWP_NOSIZE);
hd.Done = 1;
bRobotInMotion = false;
bRobotConnectInit = false;
g_hWndHapticBox = hDlg;
hd.HapticScaleX = 100;
hd.HapticScaleY = 100;
hd.HapticScaleZ = 100;
hd.MaxForcePos = 160;
hd.MaxForceNeg = -160;
hd.EnableForces = true;
hd.ForceLimitPosX = false;
hd.ForceLimitPosY = false;
hd.ForceLimitPosZ = false;
hd.ForceLimitNegX = false;
hd.ForceLimitNegY = false;
hd.ForceLimitNegZ = false;
hd.filtered_x[0,1,2] = 0; //low pass output for x
hd.filtered_y[0,1,2] = 0; //low pass output for y
hd.filtered_z[0,1,2] = 0; //low pass output for z
hd.raw_x[0,1,2] = 0; //raw haptic data for low pass x
hd.raw_y[0,1,2] = 0; //raw haptic data for low pass y
hd.raw_z[0,1,2] = 0; //raw haptic data for low pass z
hc.Xmm = GetDlgItem(g_hWndHapticBox, IDC_STATIC_X);
hc.Ymm = GetDlgItem(g_hWndHapticBox, IDC_STATIC_Y);
hc.Zmm = GetDlgItem(g_hWndHapticBox, IDC_STATIC_Z);
hc.XtoRobot = GetDlgItem(g_hWndHapticBox, IDC_STATIC_XtoRobot);
hc.YtoRobot = GetDlgItem(g_hWndHapticBox, IDC_STATIC_YtoRobot);
hc.ZtoRobot = GetDlgItem(g_hWndHapticBox, IDC_STATIC_ZtoRobot);
hc.Fx = GetDlgItem(g_hWndHapticBox, IDC_STATIC_Fx);
hc.Fy = GetDlgItem(g_hWndHapticBox, IDC_STATIC_Fy);
hc.Fz = GetDlgItem(g_hWndHapticBox, IDC_STATIC_Fz);
hc.rHz = GetDlgItem(g_hWndHapticBox, IDC_STATIC_Rate);
hc.HapticStatus = GetDlgItem(g_hWndHapticBox, IDC_STATIC_HapticStatus);
hc.RobotInMotion = GetDlgItem(g_hWndHapticBox, IDC_STATIC_RobotInMotion);
hc.RobotStatus = GetDlgItem(g_hWndHapticBox, IDC_STATIC_RobotStatus);
///////////////////////////////////////////////////////////////////////////////////////
hd.HapticConnected = false;
if (hd.HapticConnected == false)
{
DWORD nThreadID;
CreateThread(0, 0, DoConnectRobot, 0, 0, &nThreadID);
Sleep(100);
CreateThread(0, 0, DoGravity, 0, 0, &nThreadID);
hd.HapticConnected = true;
}
return (INT_PTR)TRUE;
case WM_CTLCOLORSTATIC:
if(IDC_STATIC_HapticStatus == ::GetDlgCtrlID((HWND)lParam))
{
hdc = (HDC)wParam;
if (hd.Done == 1)
{
SetBkColor(hdc, RGB(255,0,0)); //red
return (BOOL)::CreateSolidBrush(RGB(255,0,0)); //red
}
else
{
SetBkColor(hdc, RGB(0,255,0)); //green
return (BOOL)::CreateSolidBrush(RGB(0,255,0)); //green
}
}
if(IDC_STATIC_RobotStatus == ::GetDlgCtrlID((HWND)lParam))
{
hdc = (HDC)wParam;
if (bRobotConnectInit)
{
SetBkColor(hdc, RGB(250, 255, 5)); //yellow
return (BOOL)::CreateSolidBrush(RGB(250, 255, 5));
}
else if (bRobotConnected)
{
SetBkColor(hdc, RGB(0,255,0)); //green
return (BOOL)::CreateSolidBrush(RGB(0,255,0));
}
else
{
SetBkColor(hdc, RGB(255,0,0)); //red
return (BOOL)::CreateSolidBrush(RGB(255,0,0));
}
}
if(IDC_STATIC_RobotInMotion == ::GetDlgCtrlID((HWND)lParam))
{
hdc = (HDC)wParam;
if (bRobotInMotion)
{
SetBkColor(hdc, RGB(0,255,0)); //green
return (BOOL)::CreateSolidBrush(RGB(0,255,0));
}
else
{
SetBkColor(hdc, RGB(255,0,0)); //red
return (BOOL)::CreateSolidBrush(RGB(255,0,0));
}
}
break;
case WM_CLOSE:
hd.Done = 1;
EndDialog(hDlg, message);
return TRUE;
}
return (INT_PTR)FALSE;
}
There is more code associated with the solution that if it is need I can attach. My thougt was thought to just call the WM_INITDIALOG case so that basically it would be the same as closing the program out and re opening it. Any suggestions would be appericated.
Callign WM_INITDIALOG definitely won't do what you think it will. Don't send random Windows messages unless you understand them exactly.
My suggestion, given your design, would be to have your program launch another instance of itself and have the old instance exit. Look into CreateProcess on MSDN for the details on how to launch another process. I think that this will be the most maintainable and easy-to-code solution given what you already have.
I would suggest making repeated calls to DialogBox like this:
do
{
DialogBox(hInstance, (LPCTSTR)IDD_HAPTIC, NULL, HapticBox);
} while (ReOpenDialog);
Where ReOpenDialog is a global you set according to the success of your operation (or, to avoid a global, you could use the dialog return result from DialogBox via EndDialog).
Also, you don't need a message loop because DialogBox calls have their own one inside, thus creating a blocking call (which is why my above loop will work, in fact!).
I am a newbie in win32 API and I'm trying to write an app that will calculate the md5sum of a file selected through the menu or dragged and dropped in the window. I want the window to have 3 columns so that it can display the filename, path and md5sum respectively. Can someone please give me a sample code as to how to make my window look like this?
Also can someone please add the code to create the window as listbox while the menu and drag-drop options are retained?
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
OPENFILENAME ofn;
char szFileName[MAX_PATH] = "";
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(OPENFILENAME); // SEE NOTE BELOW
ofn.hwndOwner = hwnd;
ofn.lpstrFilter = L"Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
wchar_t dest[255];
mbstowcs(dest,szFileName,255);
ofn.lpstrFile = dest;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
ofn.lpstrDefExt = L"txt";
SendDlgItemMessage(hwnd, IDC_LIST, LB_ADDSTRING, 0, (LPARAM)"Hi there!");
if(Message == WM_DROPFILES)
{
HDROP hDropInfo = (HDROP)wParam;
char sItem[MAX_PATH];
for(int i = 0; DragQueryFileA(hDropInfo, i, (LPSTR)sItem, sizeof(sItem)); i++)
{
if(GetFileAttributesA(sItem) &FILE_ATTRIBUTE_DIRECTORY)
{
MessageBox(hwnd, L"Attemt to calculate md5 of a directory!", L"Error",
MB_OK | MB_ICONINFORMATION);
}
else
{
mbstowcs(dest,sItem,260);
LoadFileToGetMD5(hwnd,dest);
}
}
}
switch(Message)
{
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_FILE_OPEN:
{
if(GetOpenFileName(&ofn))
{
MessageBox(hwnd, dest, L"Notice",
MB_OK | MB_ICONINFORMATION);
LoadFileToGetMD5(hwnd,dest);
}
else
{
MessageBoxA(hwnd, "File Cannot be opened!", "Error",
MB_OK | MB_ICONINFORMATION);
}
}
break;
case ID_FILE_EXIT:
PostMessageA(hwnd, WM_CLOSE, 0, 0);
break;
case ID_STUFF_ABOUT:
{
DialogBox(GetModuleHandle(NULL),
MAKEINTRESOURCE(IDD_ABOUT), hwnd, AboutDlgProc);
}
break;
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProcA(hwnd, Message, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = MAKEINTRESOURCE(ID_MENU);
wchar_t dest[25];
mbstowcs(dest,g_szClassName,25);
wc.lpszClassName = dest;
wc.hIconSm = NULL;
char name[10]="md5sum";
if(!RegisterClassEx(&wc))
{
MessageBoxA(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hwnd = CreateWindowExA(
WS_EX_ACCEPTFILES,
g_szClassName,
"md5sum",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
NULL, NULL ,hInstance, NULL);
if(hwnd == NULL)
{
MessageBoxA(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
if(!IsDialogMessage(g_hToolbar, &Msg))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
return Msg.wParam;
}
you should search google for "listview in winapi"
btw,here is a code http://www.win32apicode.com/listview.php