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.
Related
I just want to click the button and change the text of the button, however, I would get the WM_CLOSE message, it confused me.
const wchar_t *g_szClassName = L"myWindowClass";
HWND hwnd;
HWND hButtonLine;
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
{
hButtonLine = CreateWindowW(L"BUTTON", L"change title", WS_VISIBLE | WS_CHILD, 20, 50, 150, 25, hwnd, (HMENU)ID_CHANGE_TITLE, NULL, NULL);
break;
}
case WM_COMMAND:
switch (HIWORD(wParam)) {
case BN_CLICKED:
SetWindowText(hButtonLine, L"You clicked the button");
break;
default:
break;
}
case WM_CLOSE:
if (MessageBox(hwnd, L"Really quit?", L"My application", MB_OKCANCEL) == IDOK)
{
DestroyWindow(hwnd);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
MSG Msg;
//Step 1: Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
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)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
{
MessageBox(NULL, L"Window Registration Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
L"Happy Today",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 450, 250,
NULL, NULL, hInstance, NULL);
if(hwnd == NULL)
{
MessageBox(NULL, L"Window Creation Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
oh, thks #RaymondChen, I missed the break here.
On a regular combobox, you can jump to items that starts with the typed letter. e.g., if you have items like "baa", "arch", "foo", "art" and type "a" the item "arch" gets selected, you type "a" again then it jumps to "art". How can I implement this on owner-draw combobox? I thought I could handle WM_CHAR like below in the comobobox's subprocedure, however I couldn't even test it, since setting a procedure to the comobobox like that fails:
HWND hwndEdit = GetWindow(hwndCombo, GW_CHILD);
assert(hwndEdit != NULL); // fails here
lpfnEditWndProc = (WNDPROC) SetWindowLongPtr(hwndEdit, GWLP_WNDPROC, (LONG_PTR) SubClassProc);
the procecdure was going to be like this:
LRESULT CALLBACK SubClassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CHAR:
{
static int prevIndex = 0;
static wchar_t buffer[2] = {0};
memset(&buffer, 0, sizeof(buffer));
buffer[0] = wParam;
prevIndex = SendMessage(hwndCombo, CB_FINDSTRING, (WPARAM) prevIndex, (LPARAM) buffer);
SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) prevIndex, 0);
return 0;
}
break;
}
return CallWindowProc(lpfnEditWndProc, hwnd, msg, wParam, lParam);
}
Here's the full code of owner-draw combobox:
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "Comctl32.lib")
#pragma comment(lib, "Gdi32.lib")
#pragma comment(lib, "UxTheme.lib")
#pragma comment(lib, "Comdlg32.lib")
#define WIN32_LEAN_AND_MEAN
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <Commctrl.h>
#include <assert.h>
#include <uxtheme.h>
#include <Commdlg.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void SetDefaultFont(HWND hwnd);
HFONT LoadSystemDefaultFont();
void DrawBorder(HDC hdc, RECT *rect);
void DrawLine(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2);
void freeBrushes();
HBRUSH getBrushAt(int index);
void drawColorRect(HDC dc, RECT *editRect, int colorIndex);
void EnableVisualStyles2(void);
LRESULT CALLBACK SubClassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
HINSTANCE g_hinst;
HFONT hDefaultSystemFont;
HWND hwndCombo;
#define COUNTOF(a) (sizeof(a)/sizeof(a[0]))
#define LIST \
X(L"Black", RGB(0, 0, 0)) \
X(L"Red", RGB(255, 0, 0)) \
X(L"Blue", RGB(0, 0, 255)) \
X(L"Green", RGB(0, 128, 0)) \
X(L"Yellow", RGB(255, 255, 0))
#define X(a, b) a,
const wchar_t *items[] = { LIST };
#undef X
#define X(a, b) b,
const int colorCodes[] = { LIST };
#undef X
HBRUSH brushes[COUNTOF(items)];
WNDPROC lpfnEditWndProc;
enum
{
BTN_A = 20,
BTN_COMBO,
};
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PWSTR lpCmdLine, int nCmdShow) {
HWND hwnd;
MSG msg;
WNDCLASSW wc = {0};
wc.lpszClassName = L"Application";
wc.hInstance = hInstance ;
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.lpfnWndProc = WndProc;
wc.hCursor = LoadCursor(0,IDC_ARROW);
g_hinst = hInstance;
RegisterClassW(&wc);
hwnd = CreateWindowW(wc.lpszClassName, L"Combo box",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
100, 100, 270, 170, 0, 0, hInstance, 0);
while (GetMessage(&msg, NULL, 0, 0)) {
DispatchMessage(&msg);
}
DeleteObject(hDefaultSystemFont);
freeBrushes();
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
{
hwndCombo = CreateWindow(L"Combobox", NULL,
WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST |
CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | WS_VSCROLL | WS_HSCROLL,
10, 10, 100, 110, hwnd, (HMENU) BTN_COMBO, g_hinst, NULL);
SendMessage(hwndCombo, CB_SETMINVISIBLE, 5, 0);
SetDefaultFont(hwndCombo);
COMBOBOXINFO ci = {0};
ci.cbSize = sizeof(COMBOBOXINFO);
GetComboBoxInfo(hwndCombo, &ci);
lpfnEditWndProc = (WNDPROC)SetWindowLongPtr(ci.hwndList, GWLP_WNDPROC, (LONG_PTR)SubClassProc);
for (int i = 0; i < COUNTOF(items); ++i)
{
SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) items[i]);
}
}
break;
case WM_DRAWITEM:
{
LPDRAWITEMSTRUCT b = (LPDRAWITEMSTRUCT) lParam;
SetBkMode(b->hDC, TRANSPARENT);
if(b->itemState & ODS_SELECTED)
{
FillRect(b->hDC, &b->rcItem, (HBRUSH) (COLOR_HIGHLIGHT+1));
SetTextColor(b->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT+1));
}
else
{
FillRect(b->hDC, &b->rcItem, (HBRUSH) (COLOR_WINDOW+1));
SetTextColor(b->hDC, GetSysColor(COLOR_WINDOWTEXT+1));
}
if(b->itemID != -1)
{
drawColorRect(b->hDC, &b->rcItem, b->itemID);
DrawText(b->hDC, items[b->itemID], -1, &b->rcItem, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
if(b->itemAction & ODA_FOCUS)
{
DrawFocusRect(b->hDC, &b->rcItem);
}
return (INT_PTR) TRUE;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
HFONT LoadSystemDefaultFont()
{
if(hDefaultSystemFont == NULL) {
NONCLIENTMETRICS ncm;
ncm.cbSize = sizeof(NONCLIENTMETRICS);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0);
hDefaultSystemFont = CreateFontIndirect(&ncm.lfMessageFont);
}
return hDefaultSystemFont;
}
void SetDefaultFont(HWND hwnd)
{
SendMessage(hwnd, WM_SETFONT, (LPARAM) LoadSystemDefaultFont(), TRUE);
}
void drawColorRect(HDC dc, RECT *editRect, int colorIndex)
{
assert(colorIndex >= 0 && colorIndex < COUNTOF(brushes));
assert(editRect != NULL);
RECT rt = {0};
rt.left = editRect->left + 2;
rt.top = editRect->top - 2;
rt.right = editRect->right / 5;
rt.bottom = editRect->bottom - 2;
InflateRect(&rt, -1, -1);
DrawBorder(dc, &rt);
//FrameRect(dc, &rt, getBrushAt(0));
FillRect(dc, &rt, getBrushAt(colorIndex));
}
void DrawLine(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2)
{
MoveToEx(hdc, x1, y1, NULL);
LineTo(hdc, x2, y2);
}
void DrawBorder(HDC hdc, RECT *rect)
{
DrawLine(hdc, rect->left, rect->top, rect->left, rect->bottom);
DrawLine(hdc, rect->left, rect->top, rect->right, rect->top);
DrawLine(hdc, rect->right, rect->top, rect->right, rect->bottom);
DrawLine(hdc, rect->left, rect->bottom, rect->right, rect->bottom);
}
HBRUSH getBrushAt(int index)
{
assert(index >= 0 && index < COUNTOF(brushes));
HBRUSH b = brushes[index];
if(b == NULL) {
int code = colorCodes[index];
brushes[index] = CreateSolidBrush(code);
b = brushes[index];
}
return b;
}
void freeBrushes()
{
for(int i = 0; i < COUNTOF(brushes); ++i){
DeleteObject(brushes[i]);
brushes[i] = NULL;
}
}
void EnableVisualStyles2(void)
{
TCHAR dir[MAX_PATH] = {0};
GetSystemDirectory(dir, sizeof(dir) / sizeof(*dir));
ACTCTX actCtx = {0};
actCtx.cbSize = sizeof(ACTCTX);
actCtx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID |
ACTCTX_FLAG_SET_PROCESS_DEFAULT |
ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID;
actCtx.lpSource = L"shell32.dll";
actCtx.lpAssemblyDirectory = dir;
actCtx.lpResourceName = (LPCTSTR) 124;
ULONG_PTR cookie = FALSE;
HANDLE h = CreateActCtx(&actCtx);
assert(h != INVALID_HANDLE_VALUE);
ActivateActCtx(h, &cookie);
}
LRESULT CALLBACK SubClassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CHAR:
{
static int prevIndex = 0;
static wchar_t buffer[2] = {0};
buffer[0] = wParam;
MessageBox(NULL, buffer, L"", MB_OK);
prevIndex = SendMessage(hwndCombo, CB_FINDSTRING, (WPARAM) prevIndex, (LPARAM) buffer);
SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) prevIndex, 0);
return 0;
}
break;
}
return CallWindowProc(lpfnEditWndProc, hwnd, msg, wParam, lParam);
}
UPDDATE sorry, I past the code sample from other file than the owner-draw combobox. As pointed out by #Song Zhu - MSFT, set the procedure to properly but that still doesn't process WM_CHAR.
The drop-down COMBOBOX does not have an EDIT control. Instead, it has a drop-down list.
I recommend you to use GetComboBoxInfo to get the child window of the COMBOBOX control.
Try to modify the code as:
COMBOBOXINFO ci{};
ci.cbSize = sizeof(COMBOBOXINFO);
GetComboBoxInfo(hwndCombo, &ci);
lpfnEditWndProc = (WNDPROC)SetWindowLongPtr(ci.hwndList, GWLP_WNDPROC, (LONG_PTR)SubClassProc);
Of course, you can use this code to see that hwndItem of COMBOBOXINFO returns NULL. You can adjust which handle you need to control according to your combobox type.
Edit:
Your message loop code and setting style are wrong(need CBS_HASSTRINGS), please refer to:
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
......
hwndCombo = CreateWindow(L"Combobox", NULL,
WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST |
CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | WS_VSCROLL | WS_HSCROLL | CBS_HASSTRINGS,
10, 10, 100, 110, hwnd, (HMENU) BTN_COMBO, g_hinst, NULL);
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 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
I was programming the example code from Frank Luna's book "Introduction to 3D Game Programming with DirectX 10". The code is the first Win32 example in the Appendix A: Windows Programming section.
Right now, the program compiles under both VC++ 2008/2010, but no window appears, although the debug session has started and I have to forcefully close it. I have no idea where it is, I'm not using Win32 Console mode, I have closed all other windows and no other IDE or session of VC++ is running.
Any idea why this might be happening?
PS: I have also checked my Processes. It is indeed running.
#include <Windows.h>
HWND ghMainWnd = 0;
bool InitWindowsApp(HINSTANCE instanceHandle, int show);
int Run();
LRESULT CALLBACK
WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
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_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(WHITE_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"Win32Basic",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
0,
0,
instanceHandle,
0);
if( ghMainWnd = 0 )
{
MessageBox( 0, L"Window Creation FAILED", 0, 0 );
return false;
}
ShowWindow( ghMainWnd, show );
UpdateWindow( ghMainWnd );
return true;
}
int Run()
{
MSG msg = {0};
BOOL bRet = 1;
while( bRet = GetMessage( &msg, 0, 0, 0 ) != 0 )
{
if( bRet == -1 )
{
MessageBox( 0, L"GetMessage FAILED", 0, 0 );
break;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
LRESULT CALLBACK
WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_LBUTTONDOWN:
MessageBox( 0, L"Hello, World", 0, 0 );
return 0;
case WM_KEYDOWN:
if( wParam == VK_ESCAPE )
DestroyWindow( ghMainWnd );
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
Change this:
if( ghMainWnd = 0 )
{
MessageBox( 0, L"Window Creation FAILED", 0, 0 );
return false;
}
to:
if( ghMainWnd == 0 )
{
MessageBox( 0, L"Window Creation FAILED", 0, 0 );
return false;
}
Two equals signs instead of one. :)
Wild guess: _UNICODE is not defined by project settings. Use CreateWindowW, RegisterClassW, to avoid dependency.