I've been fiddling around with custom windows using the windows API. As of such I have been working with Extended Layered Windows. I have the window drawn, and it works. However when resizing the window there is an odd flickering/glitching [(Screenshot) ][1]when the redraw/UpdateLayeredWindow (and UpdateLayeredWindowIndirect) method is called. Is there anything I'm doing wrong here?
void redrawBaseWindow(HWND window) {
RECT rect;
GetWindowRect(window, &rect);
int elipseDiam = ((rect.right - rect.left)+(rect.bottom-rect.top))/2*0.025;
HDC mainDC = GetDC(NULL);
POINT destination = { rect.left,rect.top };
POINT zero = destination;
SIZE size = { rect.right - rect.left,rect.bottom - rect.top };
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.AlphaFormat = 0;
bf.SourceConstantAlpha = 255;
HBRUSH brush = CreateSolidBrush(RGB(255, 0, 100));
HBRUSH oldbrush = SelectObject(mainDC, brush);
HPEN pen = CreatePen(PS_NULL, 0, RGB(0, 0, 0));
HPEN oldPen = SelectObject(mainDC, pen);
HBITMAP bmp = CreateCompatibleBitmap(mainDC, size.cx,size.cy);
HBITMAP oldBmp = SelectObject(mainDC, bmp);
FillRect(mainDC, &rect, CreateSolidBrush(RGB(0, 0, 0)));
Rectangle(mainDC, rect.left, rect.top + elipseDiam/2, rect.right, rect.bottom - elipseDiam/2);
Rectangle(mainDC, rect.left + elipseDiam/2, rect.top, rect.right - elipseDiam/2, rect.bottom);
UPDATELAYEREDWINDOWINFO updated = { sizeof(UPDATELAYEREDWINDOWINFO), NULL, &destination, &size, mainDC, &zero, RGB(0,0,0),&bf, ULW_COLORKEY, &rect};
UpdateLayeredWindowIndirect(window, &updated);
//BOOL error = UpdateLayeredWindow(window, NULL, &destination, &size, mainDC, &zero, RGB(0, 0, 0), &bf, ULW_COLORKEY);
SelectObject(mainDC, oldbrush);
SelectObject(mainDC, oldBmp);
SelectObject(mainDC, oldPen);
DeleteObject(brush);
DeleteObject(bmp);
DeleteObject(pen);
}
Just in case, the Window Message Proc.
long __stdcall WndProc(HWND window, unsigned int msg, WPARAM wp, LPARAM lp) {
PAINTSTRUCT ps;
HDC hdc;
TCHAR greeting[] = "Hello, World!";
RECT rect_window;
GetWindowRect(window, &rect_window);
switch (msg) {
case WM_SYSKEYDOWN:
MessageBeep(MB_ICONERROR);
case WM_CREATE:
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_NCHITTEST:;
int x = LOWORD(lp);
int y = HIWORD(lp);
if (x > rect_window.left && x<rect_window.right && y>rect_window.top && y < rect_window.top + 25)
return HTCAPTION;
if (x>=rect_window.left-3 && x<=rect_window.left+3)
return HTLEFT;
if (x >= rect_window.right - 3 && x <= rect_window.right + 3)
return HTRIGHT;
if (y >= rect_window.top - 3 && y <= rect_window.top + 3)
return HTTOP;
if (y >= rect_window.bottom - 3 && y <= rect_window.bottom + 3)
return HTBOTTOM;
break;
case WM_LBUTTONDOWN:
break;
case WM_SIZE:
redrawBaseWindow(window);
break;
case WM_PAINT:
break;
}
return DefWindowProc(window, msg, wp, lp);
}
Edit:
Gif of the glitch
Edit 2:
Using CreateCompatibleDC value into UpdateLayeredWindow [Also not working]
void redrawBaseWindow(HWND window) {
RECT rect;
GetWindowRect(window, &rect);
int elipseDiam = ((rect.right - rect.left)+(rect.bottom-rect.top))/2*0.025;
HDC mainDC = GetDC(NULL);
HDC memDC = CreateCompatibleDC(mainDC);
POINT destination = { rect.left,rect.top };
POINT zero = destination;
SIZE size = { rect.right - rect.left,rect.bottom - rect.top };
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.AlphaFormat = 0;
bf.SourceConstantAlpha = 255;
HBRUSH brush = CreateSolidBrush(RGB(255, 0, 100));
HBRUSH oldbrush = SelectObject(memDC, brush);
HPEN pen = CreatePen(PS_NULL, 0, RGB(0, 0, 0));
HPEN oldPen = SelectObject(memDC, pen);
HBITMAP bmp = CreateCompatibleBitmap(memDC, size.cx,size.cy);
HBITMAP oldBmp = SelectObject(memDC, bmp);
FillRect(memDC, &rect, CreateSolidBrush(RGB(0, 0, 0)));
Rectangle(memDC, rect.left, rect.top + elipseDiam/2, rect.right, rect.bottom - elipseDiam/2);
Rectangle(memDC, rect.left + elipseDiam/2, rect.top, rect.right - elipseDiam/2, rect.bottom);
Ellipse(memDC, rect.left + elipseDiam, rect.top + elipseDiam, rect.left, rect.top); //Top-Left
Ellipse(memDC, rect.right - elipseDiam, rect.top, rect.right, rect.top + elipseDiam); //Top-Right
Ellipse(memDC, rect.left, rect.bottom, rect.left + elipseDiam, rect.bottom - elipseDiam); //Bottom-Left
Ellipse(memDC, rect.right - elipseDiam, rect.bottom, rect.right, rect.bottom - elipseDiam); //Bottom-Right
UPDATELAYEREDWINDOWINFO updated = { sizeof(UPDATELAYEREDWINDOWINFO), NULL, &destination, &size, memDC, &zero, RGB(0,0,0),&bf, ULW_COLORKEY, &rect};
UpdateLayeredWindowIndirect(window, &updated);
//BOOL error = UpdateLayeredWindow(window, NULL, &destination, &size, mainDC, &zero, RGB(0, 0, 0), &bf, ULW_COLORKEY);
SelectObject(memDC, oldbrush);
SelectObject(memDC, oldBmp);
SelectObject(memDC, oldPen);
DeleteObject(brush);
DeleteObject(bmp);
DeleteObject(pen);
ReleaseDC(NULL,mainDC);
ReleaseDC(NULL,memDC);
}
Edit 3: DeleteDC on CreateCompatibleDC device, as well as creation of bitmap on screen DC rather than CompatibleDC
void redrawBaseWindow(HWND window) {
RECT rect;
GetWindowRect(window, &rect);
int elipseDiam = ((rect.right - rect.left)+(rect.bottom-rect.top))/2*0.025;
HDC mainDC = GetDC(NULL);
HDC memDC = CreateCompatibleDC(mainDC);
POINT destination = { rect.left,rect.top };
POINT zero = destination;
SIZE size = { rect.right - rect.left,rect.bottom - rect.top };
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.AlphaFormat = 0;
bf.SourceConstantAlpha = 255;
HBRUSH brush = CreateSolidBrush(RGB(255, 0, 100));
HBRUSH oldbrush = SelectObject(memDC, brush);
HPEN pen = CreatePen(PS_NULL, 0, RGB(0, 0, 0));
HPEN oldPen = SelectObject(memDC, pen);
HBITMAP bmp = CreateCompatibleBitmap(mainDC, size.cx,size.cy);
HBITMAP oldBmp = SelectObject(memDC, bmp);
FillRect(memDC, &rect, CreateSolidBrush(RGB(0, 0, 0)));
Rectangle(memDC, rect.left, rect.top + elipseDiam/2, rect.right, rect.bottom - elipseDiam/2);
Rectangle(memDC, rect.left + elipseDiam/2, rect.top, rect.right - elipseDiam/2, rect.bottom);
Ellipse(memDC, rect.left + elipseDiam, rect.top + elipseDiam, rect.left, rect.top); //Top-Left
Ellipse(memDC, rect.right - elipseDiam, rect.top, rect.right, rect.top + elipseDiam); //Top-Right
Ellipse(memDC, rect.left, rect.bottom, rect.left + elipseDiam, rect.bottom - elipseDiam); //Bottom-Left
Ellipse(memDC, rect.right - elipseDiam, rect.bottom, rect.right, rect.bottom - elipseDiam); //Bottom-Right
UPDATELAYEREDWINDOWINFO updated = { sizeof(UPDATELAYEREDWINDOWINFO), NULL, &destination, &size, memDC, &zero, RGB(0,0,0),&bf, ULW_COLORKEY, &rect};
UpdateLayeredWindowIndirect(window, &updated);
//BOOL error = UpdateLayeredWindow(window, NULL, &destination, &size, mainDC, &zero, RGB(0, 0, 0), &bf, ULW_COLORKEY);
SelectObject(memDC, oldbrush);
SelectObject(memDC, oldBmp);
SelectObject(memDC, oldPen);
DeleteObject(brush);
DeleteObject(bmp);
DeleteObject(pen);
DeleteDC(memDC);
ReleaseDC(NULL,mainDC);
}
Original flickering fixed. Thanks [Jonathan Pottar]
Another error has occurred however : This
void redrawBaseWindow(HWND window) {
RECT rect;
GetWindowRect(window, &rect);
int elipseDiam = ((rect.right - rect.left)+(rect.bottom-rect.top))/2*0.025;
HDC mainDC = GetDC(NULL);
HDC memDC = CreateCompatibleDC(mainDC);
POINT destination = { rect.left,rect.top };
POINT zero = destination;
SIZE size = { rect.right - rect.left,rect.bottom - rect.top };
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.AlphaFormat = 0;
bf.SourceConstantAlpha = 255;
HBRUSH brush = CreateSolidBrush(RGB(255, 0, 100));
HBRUSH oldbrush = SelectObject(memDC, brush);
HPEN pen = CreatePen(PS_NULL, 0, RGB(0, 0, 0));
HPEN oldPen = SelectObject(memDC, pen);
HBITMAP bmp = CreateCompatibleBitmap(mainDC, size.cx,size.cy);
HBITMAP oldBmp = SelectObject(memDC, bmp);
FillRect(memDC, &rect, CreateSolidBrush(RGB(0, 0, 0)));
Rectangle(memDC, rect.left, rect.top + elipseDiam/2, rect.right, rect.bottom - elipseDiam/2);
Rectangle(memDC, rect.left + elipseDiam/2, rect.top, rect.right - elipseDiam/2, rect.bottom);
Ellipse(memDC, rect.left + elipseDiam, rect.top + elipseDiam, rect.left, rect.top); //Top-Left
Ellipse(memDC, rect.right - elipseDiam, rect.top, rect.right, rect.top + elipseDiam); //Top-Right
Ellipse(memDC, rect.left, rect.bottom, rect.left + elipseDiam, rect.bottom - elipseDiam); //Bottom-Left
Ellipse(memDC, rect.right - elipseDiam, rect.bottom, rect.right, rect.bottom - elipseDiam); //Bottom-Right
UPDATELAYEREDWINDOWINFO updated = { sizeof(UPDATELAYEREDWINDOWINFO), NULL, &destination, &size, memDC, &zero, RGB(0,0,0),&bf, ULW_COLORKEY, &rect};
UpdateLayeredWindowIndirect(window, &updated);
//BOOL error = UpdateLayeredWindow(window, NULL, &destination, &size, mainDC, &zero, RGB(0, 0, 0), &bf, ULW_COLORKEY);
SelectObject(memDC, oldbrush);
SelectObject(memDC, oldBmp);
SelectObject(memDC, oldPen);
DeleteObject(brush);
DeleteObject(bmp);
DeleteObject(pen);
DeleteDC(memDC);
ReleaseDC(NULL,mainDC);
}
This thankfully fixed my issue.
Related
I'm trying to send a bitmap image to server but server can't receive a bitmap file.
I've checked sending byte in client and receiving byte in server.
Before this Question, I asked similar problem in stack overflow.
And I know I don't check sending byte and receiving byte.
so I check those, but server can't receive a bitmap. server just print gray.
send function returns 3244104 and receive function returns 3244104
Those are same. help me.........
here is my server code.
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
WPARAM wParam, LPARAM lParam)
{
HDC hdcWindow;
HDC hdcbuffer;
HBITMAP hbm = NULL;
static BITMAPINFOHEADER bi;
static WSADATA wsadata;
static SOCKET s, cs;
static SOCKADDR_IN addr = { 0 }, c_addr;
int size;
static char* buffer;
switch (iMsg)
{
case WM_CREATE:
WSAStartup(MAKEWORD(2, 2), &wsadata);
s = socket(AF_INET, SOCK_STREAM, 0);
addr.sin_family = AF_INET;
addr.sin_port = 20;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(s, (LPSOCKADDR)&addr, sizeof(addr));
WSAAsyncSelect(s, hwnd, WM_ASYNC, FD_ACCEPT);
if (listen(s, 5) == -1)
return 0;
break;
case WM_ASYNC:
switch (lParam)
{
case FD_ACCEPT:
size = sizeof(c_addr);
cs = accept(s, (LPSOCKADDR)&c_addr, &size);
WSAAsyncSelect(cs, hwnd, WM_ASYNC, FD_READ);
break;
case FD_READ:
hdcWindow = GetDC(hwnd);
hdcbuffer = CreateCompatibleDC(hdcWindow);
recv(cs, (char*)&bi, sizeof(bi), 0);
buffer = (char*)malloc(bi.biSizeImage);
int i = recv(cs, buffer, bi.biSizeImage, 0);
hbm = CreateCompatibleBitmap(hdcWindow, bi.biWidth, bi.biHeight);
SelectObject(hdcbuffer, hbm);
SetDIBits(hdcbuffer, hbm, 0, bi.biHeight, buffer, (BITMAPINFO*)&bi, DIB_RGB_COLORS);
BitBlt(hdcWindow,
0, 0,
bi.biWidth, bi.biHeight,
hdcbuffer,
0, 0,
SRCCOPY);
free(buffer);
DeleteObject(hbm);
ReleaseDC(hwnd, hdcWindow);
DeleteDC(hdcbuffer);
break;
}
break;
case WM_DESTROY:
closesocket(cs);
closesocket(s);
WSACleanup();
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, iMsg, wParam, lParam);
}
this is my client code.
HINSTANCE hinst;
char* lpbitmap = NULL;
SOCKET s;
RECT rcClient;
HDC hdcScreen;
HDC hdcWindow;
int CaptureAnImage(HWND hWnd)
{
static HDC hdcMemDC;
static HBITMAP hbmScreen;
static BITMAP bmpScreen;
hdcScreen = GetDC(NULL);
hdcWindow = GetDC(hWnd);
hdcMemDC = CreateCompatibleDC(hdcWindow);
GetClientRect(hWnd, &rcClient);
SetStretchBltMode(hdcWindow, HALFTONE);
StretchBlt(hdcWindow,
0, 0,
rcClient.right, rcClient.bottom,
hdcScreen,
0, 0,
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN),
SRCCOPY);
hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right - rcClient.left, rcClient.bottom
- rcClient.top);
SelectObject(hdcMemDC, hbmScreen);
BitBlt(hdcMemDC,
0, 0,
rcClient.right - rcClient.left, rcClient.bottom - rcClient.top,
hdcWindow,
0, 0,
SRCCOPY);
GetObject(hbmScreen, sizeof(BITMAP), &bmpScreen);
BITMAPINFOHEADER bi;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bmpScreen.bmWidth;
bi.biHeight = bmpScreen.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = 32;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
GetDIBits(hdcWindow, hbmScreen, 0, bmpScreen.bmHeight, NULL, (BITMAPINFO*)&bi,
DIB_RGB_COLORS);
if (!bi.biSizeImage)
{
bi.biSizeImage = (((bi.biWidth*bi.biBitCount + 0x1F)&~0x1F) >> 3)*bi.biHeight;
}
lpbitmap = (char*)malloc(bi.biSizeImage);
GetDIBits(hdcWindow, hbmScreen, 0,
(UINT)bmpScreen.bmHeight,
lpbitmap,
(BITMAPINFO*)&bi, DIB_RGB_COLORS);
send(s, (char*)&bi, sizeof(bi), 0);
send(s, lpbitmap, bi.biSizeImage, 0);
free(lpbitmap);
DeleteObject(hbmScreen);
DeleteObject(hdcMemDC);
ReleaseDC(NULL, hdcScreen);
ReleaseDC(hWnd, hdcWindow);
return 0;
}
help me......
I can't solve this problem......
I'm trying to send a bitmap image to server but server can't receive a bitmap file.
I've checked sending byte in client and receiving byte in server.
Before this Question, I asked similar problem in stack overflow.
And I know I don't check sending byte and receiving byte.
so I check those, but server can't receive a bitmap. server just print gray.
send function returns 3244104 and receive function returns 3244104
Those are same. help me.........
here is my server code.
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
WPARAM wParam, LPARAM lParam)
{
HDC hdcWindow;
HDC hdcbuffer;
HBITMAP hbm = NULL;
static BITMAPINFOHEADER bi;
static WSADATA wsadata;
static SOCKET s, cs;
static SOCKADDR_IN addr = { 0 }, c_addr;
int size;
static char* buffer;
switch (iMsg)
{
case WM_CREATE:
WSAStartup(MAKEWORD(2, 2), &wsadata);
s = socket(AF_INET, SOCK_STREAM, 0);
addr.sin_family = AF_INET;
addr.sin_port = 20;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(s, (LPSOCKADDR)&addr, sizeof(addr));
WSAAsyncSelect(s, hwnd, WM_ASYNC, FD_ACCEPT);
if (listen(s, 5) == -1)
return 0;
break;
case WM_ASYNC:
switch (lParam)
{
case FD_ACCEPT:
size = sizeof(c_addr);
cs = accept(s, (LPSOCKADDR)&c_addr, &size);
WSAAsyncSelect(cs, hwnd, WM_ASYNC, FD_READ);
break;
case FD_READ:
hdcWindow = GetDC(hwnd);
hdcbuffer = CreateCompatibleDC(hdcWindow);
recv(cs, (char*)&bi, sizeof(bi), 0);
buffer = (char*)malloc(bi.biSizeImage);
int i = recv(cs, buffer, bi.biSizeImage, 0);
hbm = CreateCompatibleBitmap(hdcWindow, bi.biWidth, bi.biHeight);
SelectObject(hdcbuffer, hbm);
SetDIBits(hdcbuffer, hbm, 0, bi.biHeight, buffer, (BITMAPINFO*)&bi, DIB_RGB_COLORS);
BitBlt(hdcWindow,
0, 0,
bi.biWidth, bi.biHeight,
hdcbuffer,
0, 0,
SRCCOPY);
free(buffer);
DeleteObject(hbm);
ReleaseDC(hwnd, hdcWindow);
DeleteDC(hdcbuffer);
break;
}
break;
case WM_DESTROY:
closesocket(cs);
closesocket(s);
WSACleanup();
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, iMsg, wParam, lParam);
}
this is my client code.
HINSTANCE hinst;
char* lpbitmap = NULL;
SOCKET s;
RECT rcClient;
HDC hdcScreen;
HDC hdcWindow;
int CaptureAnImage(HWND hWnd)
{
static HDC hdcMemDC;
static HBITMAP hbmScreen;
static BITMAP bmpScreen;
hdcScreen = GetDC(NULL);
hdcWindow = GetDC(hWnd);
hdcMemDC = CreateCompatibleDC(hdcWindow);
GetClientRect(hWnd, &rcClient);
SetStretchBltMode(hdcWindow, HALFTONE);
StretchBlt(hdcWindow,
0, 0,
rcClient.right, rcClient.bottom,
hdcScreen,
0, 0,
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN),
SRCCOPY);
hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right - rcClient.left, rcClient.bottom
- rcClient.top);
SelectObject(hdcMemDC, hbmScreen);
BitBlt(hdcMemDC,
0, 0,
rcClient.right - rcClient.left, rcClient.bottom - rcClient.top,
hdcWindow,
0, 0,
SRCCOPY);
GetObject(hbmScreen, sizeof(BITMAP), &bmpScreen);
BITMAPINFOHEADER bi;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bmpScreen.bmWidth;
bi.biHeight = bmpScreen.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = 32;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
GetDIBits(hdcWindow, hbmScreen, 0, bmpScreen.bmHeight, NULL, (BITMAPINFO*)&bi,
DIB_RGB_COLORS);
if (!bi.biSizeImage)
{
bi.biSizeImage = (((bi.biWidth*bi.biBitCount + 0x1F)&~0x1F) >> 3)*bi.biHeight;
}
lpbitmap = (char*)malloc(bi.biSizeImage);
GetDIBits(hdcWindow, hbmScreen, 0,
(UINT)bmpScreen.bmHeight,
lpbitmap,
(BITMAPINFO*)&bi, DIB_RGB_COLORS);
send(s, (char*)&bi, sizeof(bi), 0);
send(s, lpbitmap, bi.biSizeImage, 0);
free(lpbitmap);
DeleteObject(hbmScreen);
DeleteObject(hdcMemDC);
ReleaseDC(NULL, hdcScreen);
ReleaseDC(hWnd, hdcWindow);
return 0;
}
help me......
I can't solve this problem......
I'm trying to use GL_R8UI to pass unsigned, unnormalized data to a shader, but have found that on at least one GPU it doesn't work.
ie: this works:
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 32, 32, 0, GL_RED, GL_UNSIGNED_BYTE, pData);
but this doesn't:
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, 32, 32, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, pData);
I'm also changing the shader to use sampler2D vs usampler2D and updating the math in the shader appropriately, but finding it works on AMD/Radeon cards but fails on Intel and NVidia cards - the usampler2D always seems to return zero.
I've put together a minimal sample program here. The #define NORMALIZED switches between the two approaches.
So... my main question is: is this simply a driver problem or is there something else wrong in my code that's causing this?
To ask this question another way... what else needs to be changed to switch from GL_R8 normalized data to GL_R8UI unnormalized data, besides:
changing the call to glTextImage2D
changing from sampler2D to usampler2D in the shader
changing the shader to work with uint's instead of floats
changing the math in the shader to deal with normalized vs unnormalized data.
I've now logged an bug report with Intel: https://software.intel.com/en-us/forums/graphics-driver-bug-reporting/topic/748843
Since it was asked for here's the full example program source:
// ShaderTest.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "ShaderTest.h"
#include <stdlib.h>
#include <stdint.h>
#include <GL/gl3w.h>
#pragma comment(lib, "opengl32.lib")
#define NORMALIZED
const char* pszVertexShader = R"***(
#version 150
uniform mat4 transform;
attribute vec3 position;
varying vec2 vPosition;
void main()
{
gl_Position = transform * vec4(position,1.);
vPosition = position.xy;
}
)***";
#ifdef NORMALIZED
const char* pszFragmentShader = R"***(
#version 150
uniform sampler2D TextureData;
varying vec2 vPosition;
void main()
{
float red = texelFetch(TextureData, ivec2(0, 0), 0).r;
gl_FragColor = vec4(red , 0, 0, 1);
}
)***";
#else
const char* pszFragmentShader = R"***(
#version 150
uniform usampler2D TextureData;
varying vec2 vPosition;
void main()
{
// Original post had this wrong
// float red = float(texelFetch(TextureData, ivec2(0, 0), 0)).r/255.0;
// Fixed version - still fails on Intel GPUs though
float red = float(texelFetch(TextureData, ivec2(0, 0), 0).r)/255.0;
gl_FragColor = vec4(red, 0, 0, 1);
}
)***";
#endif
int CompileShader(GLenum type, const char* pszSource)
{
int iShader = glCreateShader(type);
glShaderSource(iShader, 1, &pszSource, NULL);
glCompileShader(iShader);
// Dump log
int length;
glGetShaderiv(iShader, GL_INFO_LOG_LENGTH, &length);
if (length != 0)
{
char* pszLog = (char*)_alloca((sizeof(char) + 10) * length);
GLsizei len;
glGetShaderInfoLog(iShader, length, &len, pszLog);
OutputDebugStringA(pszLog);
}
// Check for error
int status;
glGetShaderiv(iShader, GL_COMPILE_STATUS, &status);
if (status == 0)
{
// Clean up after failuer
glDeleteShader(iShader);
return 0;
}
// Success
return iShader;
}
// Globals
HINSTANCE hInst;
HGLRC g_hRC;
GLint g_iVertexShader = 0;
GLint g_iFragmentShader = 0;
GLint g_iShaderProgram = 0;
GLuint g_iTexture = 0;
GLuint g_iVertexBuffer = 0;
#define glCheck() assert(glGetError() == 0)
struct VERTEX
{
float x;
float y;
float z;
};
bool Setup()
{
// Compile shaders
g_iVertexShader = CompileShader(GL_VERTEX_SHADER, pszVertexShader);
g_iFragmentShader = CompileShader(GL_FRAGMENT_SHADER, pszFragmentShader);
// Link program
g_iShaderProgram = glCreateProgram();
glAttachShader(g_iShaderProgram, g_iVertexShader);
glAttachShader(g_iShaderProgram, g_iFragmentShader);
glLinkProgram(g_iShaderProgram);
// Dump log
int length;
glGetProgramiv(g_iShaderProgram, GL_INFO_LOG_LENGTH, &length);
if (length != 0)
{
char* pszLog = (char*)_alloca((sizeof(char) + 10) * length);
GLsizei len;
glGetProgramInfoLog(g_iShaderProgram, length, &len, pszLog);
OutputDebugStringA(pszLog);
}
// Check for error
int status;
glGetProgramiv(g_iShaderProgram, GL_LINK_STATUS, &status);
if (status == 0)
return false;
// Create texture
glGenTextures(1, &g_iTexture);
glBindTexture(GL_TEXTURE_2D, g_iTexture);
uint8_t* pData = (uint8_t*)_alloca(32 * 32 * sizeof(uint8_t));
memset(pData, 128, 32 * 32 * sizeof(uint8_t));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
#ifdef NORMALIZED
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 32, 32, 0, GL_RED, GL_UNSIGNED_BYTE, pData);
#else
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, 32, 32, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, pData);
#endif
glBindTexture(GL_TEXTURE_2D, 0);
// Create vertex buffer
glGenBuffers(1, &g_iVertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, g_iVertexBuffer);
VERTEX v[] = {
{ 10, 10, 0, },
{ 10, 230, 0, },
{ 310, 10, 0, },
{ 310, 230, 0, },
};
glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);
// Done
return true;
}
void Cleanup()
{
if (g_iVertexBuffer)
glDeleteBuffers(1, &g_iVertexBuffer);
if (g_iTexture)
glDeleteTextures(1, &g_iTexture);
if (g_iShaderProgram)
glDeleteProgram(g_iShaderProgram);
if (g_iVertexShader)
glDeleteShader(g_iVertexShader);
if (g_iFragmentShader)
glDeleteShader(g_iFragmentShader);
}
void Display(RECT* prc)
{
// Setup viewport
glViewport(0, 0, prc->right, prc->bottom);
// Clear background
glClearColor(0, 0, 0.5f, 1);
glClear(GL_COLOR_BUFFER_BIT);
// Setup program
glUseProgram(g_iShaderProgram);
// Bind vertex buffer
glBindBuffer(GL_ARRAY_BUFFER, g_iVertexBuffer);
// Setup vertex buffer
int aPosition = glGetAttribLocation(g_iShaderProgram, "position");
glEnableVertexAttribArray(aPosition);
glVertexAttribPointer(aPosition, 3, GL_FLOAT, false, sizeof(VERTEX), 0);
// Setup texture
glActiveTexture(GL_TEXTURE0 + 0);
glBindTexture(GL_TEXTURE_2D, g_iTexture);
int uTextureData = glGetUniformLocation(g_iShaderProgram, "TextureData");
glUniform1i(uTextureData, 0);
// Setup ortho projection
float left = 0;
float right = 320;
float top = 0;
float bottom = 240;
float fnear = -1;
float ffar = 1;
float proj[] = {
(float)(2.0 / (right - left)), 0.0f, 0.0f, 0.0f,
0.0f, (float)(2.0 / (top - bottom)), 0.0f, 0.0f,
0.0f, 0.0f, (float)(-2.0 / (ffar - fnear)), 0.0f,
(float)(-(right + left) / (right - left)), (float)(-(top + bottom) / (top - bottom)), (float)(-(ffar + fnear) / (ffar - fnear)), 1.0f
};
int uTransform = glGetUniformLocation(g_iShaderProgram, "transform");
glUniformMatrix4fv(uTransform, 1, false, proj);
// Draw
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glFlush();
}
bool InitOpenGLContext(HWND hWnd)
{
// Setup pixel format
HDC hDC = GetDC(hWnd);
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
int pf = ChoosePixelFormat(hDC, &pfd);
if (pf == 0 || !SetPixelFormat(hDC, pf, &pfd))
return false;
DescribePixelFormat(hDC, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
g_hRC = wglCreateContext(hDC);
if (!g_hRC)
return false;
// Init gl3w
wglMakeCurrent(hDC, g_hRC);
int err = gl3wInit();
if (err)
{
wglMakeCurrent(NULL, NULL);
wglDeleteContext(g_hRC);
g_hRC = NULL;
return false;
}
// Setup
if (!Setup())
{
assert(false);
Cleanup();
wglMakeCurrent(NULL, NULL);
wglDeleteContext(g_hRC);
g_hRC = NULL;
return false;
}
ReleaseDC(hWnd, hDC);
return true;
}
void CleanupOpenGLContext(HWND hWnd)
{
HDC hDC = GetDC(hWnd);
wglMakeCurrent(hDC, g_hRC);
Cleanup();
wglMakeCurrent(NULL, NULL);
ReleaseDC(hWnd, hDC);
wglDeleteContext(g_hRC);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
RECT rc;
GetClientRect(hWnd, &rc);
HDC hdc = BeginPaint(hWnd, &ps);
wglMakeCurrent(hdc, g_hRC);
Display(&rc);
wglMakeCurrent(NULL, NULL);
EndPaint(hWnd, &ps);
}
break;
case WM_CLOSE:
PostQuitMessage(0);
break;
case WM_ERASEBKGND:
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
// Register Class
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SHADERTEST));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = L"ShaderTest";
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
RegisterClassExW(&wcex);
// Create Window
HWND hWnd = CreateWindowW(L"ShaderTest", L"ShaderTest", WS_OVERLAPPEDWINDOW,
50, 50, 100, 100, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
return 7;
RECT rc;
rc.left = 0;
rc.top = 0;
rc.right = 320;
rc.bottom = 240;
AdjustWindowRect(&rc, GetWindowLong(hWnd, GWL_STYLE), FALSE);
SetWindowPos(hWnd, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
if (!InitOpenGLContext(hWnd))
{
DestroyWindow(hWnd);
return 7;
}
// Show window
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// Main message loop:
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
CleanupOpenGLContext(hWnd);
DestroyWindow(hWnd);
return (int) msg.wParam;
}
Integer textures need to have nearest filtering (not linear or mipmap):
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
So actually i got a very fast and nice code from "Vodemki" in here -
Get Pixel color fastest way?
But only problem it scans the whole image while i need to scan only
my current mouse position
Here's the code -
HDC hdc, hdcTemp;
RECT rect;
BYTE* bitPointer;
int x, y;
int red, green, blue, alpha;
while(true)
{
hdc = GetDC(HWND_DESKTOP);
GetWindowRect(hWND_Desktop, &rect);
int MAX_WIDTH = rect.right;
int MAX_HEIGHT = rect.bottom;
hdcTemp = CreateCompatibleDC(hdc);
BITMAPINFO bitmap;
bitmap.bmiHeader.biSize = sizeof(bitmap.bmiHeader);
bitmap.bmiHeader.biWidth = MAX_WIDTH;
bitmap.bmiHeader.biHeight = MAX_HEIGHT;
bitmap.bmiHeader.biPlanes = 1;
bitmap.bmiHeader.biBitCount = 32;
bitmap.bmiHeader.biCompression = BI_RGB;
bitmap.bmiHeader.biSizeImage = MAX_WIDTH * 4 * MAX_HEIGHT;
bitmap.bmiHeader.biClrUsed = 0;
bitmap.bmiHeader.biClrImportant = 0;
HBITMAP hBitmap2 = CreateDIBSection(hdcTemp, &bitmap, DIB_RGB_COLORS, (void**)(&bitPointer), NULL, NULL);
SelectObject(hdcTemp, hBitmap2);
BitBlt(hdcTemp, 0, 0, MAX_WIDTH, MAX_HEIGHT, hdc, 0, 0, SRCCOPY);
for (int i=0; i<(MAX_WIDTH * 4 * MAX_HEIGHT); i+=4)
{
red = (int)bitPointer[i];
green = (int)bitPointer[i+1];
blue = (int)bitPointer[i+2];
alpha = (int)bitPointer[i+3];
x = i / (4 * MAX_HEIGHT);
y = i / (4 * MAX_WIDTH);
if (red == 255 && green == 0 && blue == 0)
{
SetCursorPos(x,y);
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
Sleep(50);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
Sleep(25);
}
}
}
I'm not familiar with BitBlt, So if anyone can help me modify that code i'll appreciate it
Thanks!
Alright I made it finally.
I still got problem with the timing, makes my puter very slow...
I'll work for it later...
Here's the code -
//Globals
int sX, sY, x, y;
BYTE* sData = 0;
POINT cursorPos;
HDC hScreen;
HDC hdcMem;
HBITMAP hBitmap;
HGDIOBJ hOld;
void PixelFunction(); // Get the pixel rgb function
int main()
{
PixelFunction();
ReleaseDC(NULL, hScreen);
DeleteDC(hdcMem);
return 0;
}
void PixelFunction()
{
int Red, Green, Blue;
hScreen = GetDC(NULL);
sX = GetDeviceCaps(hScreen, HORZRES);
sY = GetDeviceCaps(hScreen, VERTRES);
hdcMem = CreateCompatibleDC (hScreen);
hBitmap = CreateCompatibleBitmap(hScreen, sX, sY);
BITMAPINFOHEADER bm = {0};
bm.biSize = sizeof(BITMAPINFOHEADER);
bm.biPlanes = 1;
bm.biBitCount = 32;
bm.biWidth = sX;
bm.biHeight = -sY;
bm.biCompression = BI_RGB;
bm.biSizeImage = 0; // 3 * sX * sY;
while (1) {
hOld = SelectObject(hdcMem, hBitmap);
BitBlt(hdcMem, 0, 0, sX, sY, hScreen, 0, 0, SRCCOPY);
SelectObject(hdcMem, hOld);
free(sData);
sData = (BYTE*)malloc(4 * sX * sY);
GetDIBits(hdcMem, hBitmap, 0, sY, sData, (BITMAPINFO*)&bm, DIB_RGB_COLORS);
GetCursorPos(&cursorPos);
x = cursorPos.x;
y = cursorPos.y;
Red = sData[4 * ( (y * sX) + x) +2];
Green = sData[4 * ( ( y * sX) + x) +1];
Blue = sData[4 * ( (y * sX) + x)];
// Check for color
if (Red == 255 && Green == 0 && Blue == 0) {
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
Sleep(5);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
}
Sleep(10);
}
}
Hope it helped!
I am coding my first program with GUI using only pure WinAPI. But I faced some strange problem.
There are 2 ListView elements on the form to output some values. When scrollbar appears on second ListView, all child objects on the form disappears. And scrollbar of that ListView is flickering. And when I push on that ListView all get back to normal. I don't know what to do.
But this problem applies only to the second ListView element, hListViewCh on the form. There is all ok with the first element.
Here is the code:
case WM_CREATE:
{
GetClientRect(hWnd, &Rect);
h_Chk1 = CreateWindow(TEXT("button"), TEXT("Graphic"),
WS_VISIBLE | WS_CHILD | BS_CHECKBOX,
Rect.right - 550,
300 + 10,
100,
20,
hWnd, (HMENU)0xCB01, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL);
h_Chk2 = CreateWindow(TEXT("button"), TEXT("Diagram"),
WS_VISIBLE | WS_CHILD | BS_CHECKBOX,
Rect.right - 550,
300 + 35,
100,
20,
hWnd, (HMENU)0xCB02, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL);
CheckDlgButton(hWnd, 0xCB01, BST_UNCHECKED);
CheckDlgButton(hWnd, 0xCB02, BST_UNCHECKED);
hListViewCh = CreateWindow(
WC_LISTVIEW,
_T("MyList"),
LVS_REPORT|WS_CHILD|WS_VISIBLE,
Rect.right - 265,
377,
250,
200,
hWnd, (HMENU)listViewCh, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL);
//--
LVCOLUMN lvColumn = {0};
lvColumn.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT;
lvColumn.fmt = LVCFMT_CENTER;
lvColumn.pszText = "№";
lvColumn.cx = 30;
ListView_InsertColumn(hListViewCh, 0, &lvColumn);
lvColumn.pszText = "Property";
lvColumn.cx = 70;
ListView_InsertColumn(hListViewCh, 1, &lvColumn);
lvColumn.pszText = "Value";
lvColumn.cx = 120;
ListView_InsertColumn(hListViewCh, 2, &lvColumn);
//--
hListView = CreateWindow(
WC_LISTVIEW,
_T("Set of variate values"),
LVS_REPORT|WS_CHILD|WS_VISIBLE,
Rect.right - 550,
Rect.top + 15,
535,
275,
hWnd,
(HMENU)listView,
(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
NULL);
//--
lvColumn.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT;
lvColumn.pszText = "No";
lvColumn.fmt = LVCFMT_CENTER;
lvColumn.cx = 43;
ListView_InsertColumn(hListView, 0, &lvColumn);
//--
lvColumn.pszText = "[ a[i-1] , a[i] )";
lvColumn.cx = 151;
ListView_InsertColumn(hListView, 1, &lvColumn);
//--
lvColumn.pszText = "xi";
lvColumn.cx = 85;
ListView_InsertColumn(hListView, 2, &lvColumn);
//--
lvColumn.pszText = "ni";
ListView_InsertColumn(hListView, 3, &lvColumn);
//--
lvColumn.pszText = "V";
ListView_InsertColumn(hListView, 4, &lvColumn);
//--
lvColumn.pszText = "EV";
ListView_InsertColumn(hListView, 5, &lvColumn);
break;
}
There is some redraw functions in WM_PAINT to make ListViews move with a window on maximizing.
//-- LISTVIEW POSITION
SetWindowPos(hListViewCh, NULL,\
Rect.right - 265,
312,
250,
200,
SWP_NOSIZE);
//-- LISTVIEW POSITION
SetWindowPos(hListView, NULL,\
Rect.right - 550,\
Rect.top + 15,\
535,\
340,\
SWP_NOSIZE|SWP_NOZORDER);
//--
Resizing child windows in a WM_PAINT is simply wrong and I suspect this to be a big part of your problems.
The code to position the child windows should be run in response to the WM_WINDOWPOSCHANGED message.