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
Related
We have updated our windows code to use Styles and since then we get a flicker in various parts of the code when using STM_SETIMAGE to update a bitmap on a window.
I have created a minimal reproducible example here. Can anyone tell me what I need to do to get rid of the flicker please ?
The code simply redraws a bitmap every 1/100 second and calls the windows function to set the image onto the window. It worked without a flicker before we added Windows Styles.
Thanks
Shaun
#include <windows.h>
#include <CommCtrl.h>
#include <math.h>
#include <objbase.h>
#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
//--------------------------------------
#ifndef HINST_THISCOMPONENT
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
#endif
//--------------------------------------
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
return DefWindowProc(hwnd, message, wParam, lParam);
}
//--------------------------------------
HWND logo;
HWND m_hwnd;
HBITMAP testBitmap;
int counter=0;
typedef unsigned char u8;
typedef unsigned int u32;
//--------------------------------------
HRESULT App_Initialize()
{
HRESULT hr;
// Register the window class.
WNDCLASSEX wcex = { sizeof(WNDCLASSEX) };
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = sizeof(LONG_PTR);
wcex.hInstance = HINST_THISCOMPONENT;
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);;
wcex.lpszMenuName = NULL;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.lpszClassName = TEXT("myApp");
RegisterClassEx(&wcex);
int dpiX = 0;
int dpiY = 0;
HDC hdc = GetDC(NULL);
if (hdc)
{
dpiX = GetDeviceCaps(hdc, LOGPIXELSX);
dpiY = GetDeviceCaps(hdc, LOGPIXELSY);
ReleaseDC(NULL, hdc);
}
m_hwnd = CreateWindow( TEXT("myApp"), TEXT("Simple Set image Example"), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, 640, 640, NULL,NULL,HINST_THISCOMPONENT,0);
hr = m_hwnd ? S_OK : E_FAIL;
if (SUCCEEDED(hr))
{
ShowWindow(m_hwnd, SW_SHOWNORMAL);
UpdateWindow(m_hwnd);
}
logo = CreateWindow("Static", NULL, SS_BITMAP | WS_CHILD | WS_VISIBLE, 40, 40,512,512, m_hwnd, NULL, NULL, NULL);
return hr;
}
//----------------------------------------------
void Redraw()
{
DeleteObject(testBitmap);
testBitmap=0;
u8 * RenderImageData=(u8*)malloc(512*512*4);
u32 * p=(u32*)RenderImageData;
for(int i=0;i<512;i++)
{
p[i+counter*512]=0xff000000;
p[i*512+counter]=0xff000000;
}
testBitmap = CreateBitmap(512,512, 4, 8, RenderImageData);
SendMessage(logo,STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) testBitmap);
free(RenderImageData);
counter=(counter+1)&511;
}
//----------------------------------------------
int WINAPI WinMain(HINSTANCE hInstance ,HINSTANCE hPrevInstance ,LPSTR lpCmdLine ,int nCmdShow)
{
if (SUCCEEDED(CoInitialize(NULL)))
{
if (SUCCEEDED(App_Initialize()))
{
MSG msg;
while(1)
{
while (PeekMessage(&msg, NULL, 0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Sleep(10);
Redraw();
}
}
CoUninitialize();
}
return 0;
}
//----------------------------------------------
I found this code which seems to work.
Instead of
HBITMAP hbm=(HBITMAP)SendMessage(hWndPic,STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) pD->hbitmap);
I call
GDI_SetImageX(pD->hbitmap,hWndPic, xs, ys);
void GDI_SetImageX( HBITMAP hBM, HWND hCtrl , int w, int h)
{
HDC hdcSrc=CreateCompatibleDC(0);
HDC hdcDst=GetDC(hCtrl);
HGDIOBJ hbmOld=SelectObject(hdcSrc,hBM);
HGDIOBJ hbmNew=CreateBitmap(w,h,4,8,0);
HGDIOBJ hbmOld2=SelectObject(hdcDst,hbmNew);
BitBlt(hdcDst,0,0,w,h,hdcSrc,0,0,0x00cc0020);
SelectObject(hdcSrc,hbmOld);
DeleteDC(hdcSrc);
ReleaseDC(hCtrl,hdcDst);
SendMessage(hCtrl,0x0b,0,0);
LRESULT oBM=SendMessage(hCtrl,STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hBM);
SendMessage(hCtrl,0x0b,1,0);
DeleteObject(hBM);
}
I need to get the whole window's display area size, including controls that are hidden. In order to do that, I get the value from top from the very first window and the value of bottom from very last control. However, I'm getting a gap/white are in the end of the display area. See what's like in the below image. The display area is supposed to be until the Edit control's borders is seen. What am I missing?
I'm getting this size by:
int scrollHeight(void)
{
int minTop = 0;
int maxBottom = 0;
RECT rt = {0};
if(allControls_indx == 0) {
return 0;
}
#if 0
assert(allControls[0] == hMainWindow);
assert(allControls[allControls_indx - 1] == hEdit1);
#endif
if(!GetWindowRect(allControls[0], &rt)) {
ErrorExit(NAMEOF(scrollHeight), __LINE__, __FILENAME__);
}
minTop = rt.top;
if(!GetWindowRect(allControls[allControls_indx - 1], &rt)) {
ErrorExit(NAMEOF(scrollHeight), __LINE__, __FILENAME__);
}
maxBottom = rt.bottom;
return maxBottom - minTop;
}
set as scrollbar's page size like this:
setUpScrollBar(hwnd, scrollHeight());
where setUpScrollBar is defined as:
void setUpScrollBar(HWND hwnd, int h)
{
RECT rc = { 0 };
GetClientRect(hwnd, &rc);
SCROLLINFO si = { 0 };
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_ALL;
si.nMin = 0;
si.nMax = h;
si.nPage = (rc.bottom - rc.top);
si.nPos = 0;
si.nTrackPos = 0;
SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
}
full code:
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "Comctl32.lib")
#pragma comment(lib, "Gdi32.lib")
#define WIN32_LEAN_AND_MEAN
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <Commctrl.h>
#include <crtdbg.h>
#include <strsafe.h>
#include <string.h>
#include <assert.h>
#ifdef UNICODE
#define STRSPLIT wcsrchr
#else
#define STRSPLIT strrchr
#endif
#define __FILENAME__ (STRSPLIT(TEXT(__FILE__), '/') ? STRSPLIT(TEXT(__FILE__), '/') + 1 : TEXT(__FILE__))
#define NAMEOF(s) TEXT(#s)
#define COUNTOF(a) (sizeof(a)/sizeof(a[0]))
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK CreateTabProc(HWND, UINT, WPARAM, LPARAM);
void ErrorExit(LPWSTR lpszFunction, int line, LPWSTR filename);
void InitComControls();
void ErrorExit(LPWSTR lpszFunction, int line, LPWSTR filename);
DWORD ShowLastError(LPWSTR lpszFunction, int line, LPWSTR filename);
void InitComControls();
void CreateTab(HWND hwnd);
void InsertTabItem(HWND tabHwnd, UINT id, LPWSTR text);
void CreateButtons(HWND hwnd);
RECT GetLocalCoordinates(HWND hWnd);
int scrollHeight(void);
int getHeight(HWND control);
void setUpScrollBar(HWND hwnd, int);
void pushControl(HWND);
int displayArea(void);
void setScrollBarSize(HWND hwnd, int s);
inline int my_max(int a, int b);
inline int my_min(int a, int b);
void displayText(HWND h);
HINSTANCE ghInstance;
HWND hTab;
HWND hLabel1, hLabel2;
HWND hEdit1;
HWND hRemoveButton;
enum
{
IDBUTTON_REMOVE = 50
};
#define MAX_CONTROLS 8
static const wchar_t *title[] = { L"Button A1", L"Button B2", L"Button C3",
L"Button D4", L"Button E5", L"Button F6",
L"Button G" , L"Button 001", L"Button 002",
L"Button 003", L"Button 004",
L"Button 005", L"Button 006" };
HWND hButton[sizeof(title)/sizeof(title[0])] = {0};
HWND allControls[MAX_CONTROLS];
HWND hMainWindow;
int allControls_indx = 0;
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PWSTR pCmdLine, int nCmdShow)
{
MSG msg = {0};
HWND hwnd;
WNDCLASSW wc = {0};
wc.lpszClassName = L"Window";
wc.hInstance = hInstance;
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.lpfnWndProc = WndProc;
wc.hCursor = LoadCursor(0, IDC_ARROW);
InitComControls();
if(!RegisterClass(&wc)) {
ErrorExit(NAMEOF(RegisterClass), __LINE__, __FILENAME__);
}
int width = 500;
int height = 350/2; // half than the usual size, so that the scrollbar show up and we can test it
int screenWidth = GetSystemMetrics(SM_CXSCREEN);
int screenHeight = GetSystemMetrics(SM_CYSCREEN);
int cx = (screenWidth - width) / 2;
int cy = (screenHeight - height) / 2;
hwnd = CreateWindowW(wc.lpszClassName, L"main window",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
cx, cy, width, height, NULL, NULL,
hInstance, NULL);
ghInstance = hInstance;
while (GetMessage(&msg, NULL, 0, 0))
{
if (!IsDialogMessage(hwnd, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static int g_scrollY;
switch(msg)
{
case WM_CREATE:
hMainWindow = hwnd;
pushControl(hwnd); // push main window too
hLabel1 = CreateWindowW(L"Static", L"This is label 1...",
WS_VISIBLE | WS_CHILD | WS_TABSTOP,
50, 10, 130, 25, hwnd, (HMENU) 18, NULL, NULL);
pushControl(hLabel1);
hLabel2 = CreateWindowW(L"Static", L"This is label 2...",
WS_VISIBLE | WS_CHILD | WS_TABSTOP,
50, 40, 130, 25, hwnd, (HMENU) 19, NULL, NULL);
hRemoveButton = CreateWindow(L"Button", L"Remove",
WS_VISIBLE | WS_CHILD | WS_TABSTOP,
200, 40, 80, 25,
hwnd,
(HMENU) IDBUTTON_REMOVE,
NULL,
NULL);
pushControl(hLabel2);
CreateTab(hwnd);
CreateButtons(hwnd);
setUpScrollBar(hwnd, scrollHeight());
break;
case WM_VSCROLL:
{
int action = LOWORD(wParam);
//HWND hScroll = (HWND)lParam;
int pos = -1;
if (action == SB_THUMBPOSITION || action == SB_THUMBTRACK) {
pos = HIWORD(wParam);
} else if (action == SB_LINEDOWN) {
pos = g_scrollY + 30;
} else if (action == SB_LINEUP) {
pos = g_scrollY - 30;
}
if (pos == -1)
break;
SCROLLINFO si = { 0 };
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_POS;
si.nPos = pos;
si.nTrackPos = 0;
SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
GetScrollInfo(hwnd, SB_VERT, &si);
pos = si.nPos;
POINT pt;
pt.x = 0;
pt.y = pos - g_scrollY;
HDC hdc = GetDC(hwnd);
LPtoDP(hdc, &pt, 1);
ReleaseDC(hwnd, hdc);
ScrollWindow(hwnd, 0, -pt.y, NULL, NULL);
g_scrollY = pos;
return 0;
}
break;
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case IDBUTTON_REMOVE:
ShowWindow(hEdit1, SW_HIDE);
SetScrollRange(hwnd, SB_VERT, 0, displayArea(), TRUE);
break;
}
}
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
// this is like scrollHeight but control that are hidden
// aren't considered part of the display area.
int displayArea(void)
{
int size = scrollHeight();
// start i with 1 so we skip the mainwindow.
// we are interested in the "children controls"
for(int i = 1; i < MAX_CONTROLS && allControls[i]; i++)
{
HWND h = allControls[i];
// if it not visible, remove it from display area
if(!IsWindowVisible(h)) {
size -= getHeight(h);
}
}
return size;
}
void pushControl(HWND hwnd)
{
if(allControls_indx > MAX_CONTROLS) {
assert(!"no room for extra controls");
}
allControls[allControls_indx++] = hwnd;
}
void CreateTab(HWND hwnd)
{
hTab =
CreateWindow(WC_TABCONTROLW, NULL,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_TABSTOP,
100, 80, 400, 250,
hwnd,
(HMENU) 1,
NULL,
NULL);
InsertTabItem(hTab, 2, L"Tab 1");
InsertTabItem(hTab, 3, L"Tab b");
pushControl(hTab);
}
void CreateButtons(HWND hwnd)
{
RECT rt = GetLocalCoordinates(hTab);
TabCtrl_AdjustRect(hTab, FALSE, &rt);
RECT rt2 = {0};
GetWindowRect(hTab, &rt2);
int tab_width = rt2.right - rt2.left;
int tab_height = rt2.bottom - rt2.top;
int id = 4;
const int cy_breakSize = 25;
int cx_initPos = rt.left;
int cy_initPos = rt.top;
int cx = cx_initPos;
int cy = cy_initPos;
const int button_width = 80;
const int button_height = 25;
const int cx_margin = 10;
int nMaxButtonPerRow = tab_width / (button_width + cx_margin);
for(int i = 0; i < sizeof(title)/sizeof(title[0]); ++i)
{
if(i != 0 && (i % nMaxButtonPerRow) == 0) {
cy += cy_breakSize;
cx = cx_initPos;
}
hButton[i] =
CreateWindow(L"button", title[i],
WS_VISIBLE | WS_CHILD | WS_TABSTOP,
cx,
cy,
button_width,
button_height,
hwnd, (HMENU) id++, NULL, NULL);
cx += button_width;
}
const int edit_width = 180;
const int edit_height = 25;
hEdit1 = CreateWindow(L"Edit", L"Hello, world!",
WS_VISIBLE | WS_CHILD | WS_BORDER,
cx,
// put below tab control's display area
getHeight(hTab) + cx,
edit_width,
edit_height,
hwnd,
(HMENU) id++,
NULL, NULL);
pushControl(hEdit1);
cx += edit_width;
}
void setUpScrollBar(HWND hwnd, int h)
{
RECT rc = { 0 };
GetClientRect(hwnd, &rc);
SCROLLINFO si = { 0 };
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_ALL;
si.nMin = 0;
si.nMax = h;
si.nPage = (rc.bottom - rc.top);
si.nPos = 0;
si.nTrackPos = 0;
SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
}
void setScrollBarSize(HWND hwnd, int s)
{
SCROLLINFO si = { 0 };
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_RANGE;
si.nMin = 0;
si.nMax = s;
SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
}
int getHeight(HWND control)
{
RECT rt;
if(!GetWindowRect(control, &rt)) {
ErrorExit(NAMEOF(getHeight), __LINE__, __FILENAME__);
}
return rt.bottom - rt.top;
}
void displayText(HWND h)
{
int len = GetWindowTextLength(h);
if(len == 0) {
return;
}
wchar_t buffer[len + 1];
memset(buffer, 0, sizeof(buffer));
GetWindowText(h, buffer, len+1);
MessageBox(NULL, buffer, L"control text = ", MB_OK);
}
int scrollHeight(void)
{
int minTop = 0;
int maxBottom = 0;
RECT rt = {0};
if(allControls_indx == 0) {
return 0;
}
#if 0
assert(allControls[0] == hMainWindow);
assert(allControls[allControls_indx - 1] == hEdit1);
#endif
if(!GetWindowRect(allControls[0], &rt)) {
ErrorExit(NAMEOF(scrollHeight), __LINE__, __FILENAME__);
}
minTop = rt.top;
if(!GetWindowRect(allControls[allControls_indx - 1], &rt)) {
ErrorExit(NAMEOF(scrollHeight), __LINE__, __FILENAME__);
}
maxBottom = rt.bottom;
return maxBottom - minTop;
}
RECT GetLocalCoordinates(HWND hWnd)
{
RECT Rect;
GetWindowRect(hWnd, &Rect);
MapWindowPoints(HWND_DESKTOP, GetParent(hWnd), (LPPOINT) &Rect, 2);
return Rect;
}
void InsertTabItem(HWND tabHwnd, UINT id, LPWSTR text)
{
TCITEMW tci = {0};
tci.mask = TCIF_TEXT;
tci.pszText = text;
tci.cchTextMax = lstrlenW(text);
SendMessage(tabHwnd, TCM_INSERTITEM, id, (LPARAM) &tci);
}
void InitComControls()
{
INITCOMMONCONTROLSEX icex;
/* initialize this component is required to use tab control,
it seems.
*/
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_TAB_CLASSES;
InitCommonControlsEx(&icex);
}
// display the error message from last error seen then
// exit the application, with that last error code seen.
// to test function, do something like:
// if(!GetProcessId(NULL))
// errorExit(TEXT("GetProcessId"));
// not quite a unittest but yeah.
void ErrorExit(LPWSTR lpszFunction, int line, LPWSTR filename)
{
DWORD dw = ShowLastError(lpszFunction, line, filename);
ExitProcess(dw);
}
DWORD ShowLastError(LPWSTR lpszFunction, int line, LPWSTR filename)
{
#define MAX_DIGITS 16
/*
* NOTE!!: calling GetLastError() must be done before calling
* any other function, that would reset the GetLastError(), making
* this function report error about the wrong function.
*/
DWORD dw = GetLastError();
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0,
NULL
);
lpDisplayBuf = (LPVOID) LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf) +
lstrlen((LPCTSTR)lpszFunction) + 40 +
(line > 0 ? MAX_DIGITS : 0) +
(filename != NULL ? lstrlen(filename) : 0)) *
sizeof(TCHAR)
);
StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s failed with %d: %s"),
lpszFunction, dw, lpMsgBuf
);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
return dw;
}
I think there is no problem with your calculation method. But you added the handle of the main window hwnd for the first time, which leads to the fact that the minTop you get in GetWindowRect(allControls[0], &rt) is the top coordinate of the main window, which caused a gap at the end of the display area.
However, you should actually get the coordinates of minTop from hLabel1 so that you won't attend the question.
In addition, you forgot to add hRemoveButton to the allControls array.
Solution: You can choose not to add the main window to the allControls array, or use GetWindowRect(allControls[1], &rt) to get the coordinates of minTop.
if (!GetWindowRect(allControls[1], &rt)) {
ErrorExit((LPWSTR)NAMEOF(scrollHeight), __LINE__, (LPWSTR)__FILENAME__);
}
minTop = rt.top;
Edit:
The reason why part of the edit box is cropped is that your hLabel1 is set to a height of 10 compared to the top, so when the top of hLabel1 is used as minTop, the length of the bottom is reduced by 10 units.
You need to add the y size of the topmost control:
return maxBottom - minTop + y; //The y size of the topmost control.
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.
I am trying out the win32 api so I decided to try to draw a checkers board on a windows, just for testing
it happens that I can draw the checkers board and I tried to implement some interactivity on it. To do it so, I am storing the mouse click on a static and using it on the WM_PAINT to draw a red border around the clicked house.
the problem is that after a few clicks the windows freaks out, screen gets all white without the brushes fill and I can find the window title, it a complete mess.
This is the code I have
#include <windows.h>
#include "WindowsX.h"
#include "stdafx.h"
#include <vector>
#include <stdlib.h>
//const char g_szClassName[] = "myWindowClass";
POINT p;
void TabuleiroCasas(std::vector<RECT>* rc, RECT rcClient)
{
for(int i = 0; i < 8; i++)
{
for(int j = 0; j < 8; j++)
{
int width = (rcClient.right-200 - rcClient.left) / 8;
int height = (rcClient.bottom - rcClient.top) / 8;
RECT r;
r.left = width*j;
r.top = rcClient.bottom - (height * i);
r.right = width*(j+1);
r.bottom = rcClient.bottom - height * (i+1);
rc->push_back(r);
}
}
}
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
HPEN hPen = CreatePen(PS_SOLID, 1, RGB(255,255,255));
HPEN hPenSel = CreatePen(PS_SOLID, 3, RGB(255,0,0));
HBRUSH hBrushgrey =CreateSolidBrush(RGB(200,200,200));
HBRUSH hBrushblack =CreateSolidBrush(RGB(255,255,255));
HBRUSH hBrushwhite = CreateSolidBrush(RGB(0,0,0));
PAINTSTRUCT Ps;
std::vector<RECT> casas;
int xPos;
int yPos;
switch(msg)
{
case WM_LBUTTONDOWN:
GetCursorPos(&p);
InvalidateRect(hwnd, NULL, true);
break;
case WM_PAINT:
try
{
RECT rcClient;
GetClientRect(hwnd, &rcClient);
HDC hdc;
//DESENHA TABULEIRO
hdc = BeginPaint(hwnd, &Ps);
SelectObject(hdc, hBrushgrey);
Rectangle(hdc, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
Rectangle(hdc, rcClient.left, rcClient.top, rcClient.right-200, rcClient.bottom);
TabuleiroCasas(&casas, rcClient);
for(int i = 0; i < casas.size(); i++)
{
if ( ((i + (i / 8)) % 2) == 1)
{
SelectObject(hdc, hBrushwhite);
Rectangle(hdc, casas[i].left ,casas[i].bottom, casas[i].right, casas[i].top);
}
else
{
SelectObject(hdc, hBrushblack);
Rectangle(hdc, casas[i].left ,casas[i].bottom, casas[i].right, casas[i].top);
}
}
for(int i = 0; i < casas.size(); i++)
{
if((p.x > casas[i].left) && (p.x < casas[i].right) && (p.y < casas[i].top) && (p.y > casas[i].bottom))
{
SelectObject(hdc, hPenSel);
Rectangle(hdc, casas[i].left ,casas[i].bottom, casas[i].right, casas[i].top);
}
}
EndPaint(hwnd, &Ps);
}
catch(int e)
{
}
break;
case WM_SIZE:
//InvalidateRect(hwnd, NULL, false);
break;
case WM_CLOSE:
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;
HWND hwnd;
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 = L"Damas";
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
{
MessageBox(NULL, L"Window Registration Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
// Step 2: Creating the Window
hwnd = CreateWindowEx(
3,
L"Damas",
L"The title of my window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 800, 600,
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);
// Step 3: The Message Loop
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
The problem can be found right at the top of your window procedure. You are creating a bunch of GDI objects every time your WndProc is called:
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
HPEN hPen = CreatePen(PS_SOLID, 1, RGB(255,255,255));
HPEN hPenSel = CreatePen(PS_SOLID, 3, RGB(255,0,0));
HBRUSH hBrushgrey =CreateSolidBrush(RGB(200,200,200));
HBRUSH hBrushblack =CreateSolidBrush(RGB(255,255,255));
HBRUSH hBrushwhite = CreateSolidBrush(RGB(0,0,0));
.....
}
You don't ever return these to the system and so eventually you exhaust available GDI resources. Create those objects once only at application initialization time.
That call to DeleteDC looks very suspicious to me. You certainly do not need it. Remove it.
Another problem that you have is the code to retrieve the mouse position. You never use GetCursorPos for that since the mouse may have moved since the message was posted. You can get it from lParam. Like this:
p.x = GET_X_LPARAM(lParam);
p.y = GET_Y_LPARAM(lParam);
You'll need to include the Windowsx header properly. It's done like this:
#include <WindowsX.h>
Note the difference from your code in the question.
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