I have a simple list view which has an image list added to it. Displaying image items is fine, but when I just want one piece of text, no icon or image, one pure text item into my list view, the thing drops an image on me. I can't add any item without it having an icon/image next to it.
Here's the code
case WM_CREATE:{
HBITMAP hbmp_o, hbmp;
COLORREF crMask;
// listview view is LVS_ICON by default
hWndListView = CreateWindowEx(0, WC_LISTVIEW, TEXT("ListView1"), WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL, 0, 0, 400, 500, hwnd, NULL, GetModuleHandle(NULL), NULL);
hbmp_o = (HBITMAP)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP3), IMAGE_BITMAP, 0, 0, 0);
BITMAP bm_o = { 0 };
GetObject(hbmp_o, sizeof(bm_o), &bm_o);
HDC dc_o = CreateCompatibleDC(NULL), dc = CreateCompatibleDC(NULL);
HBITMAP old_o = (HBITMAP)SelectObject(dc_o, hbmp_o);
unsigned char *Data;
BITMAPINFO BitmapInfo;
memset(&BitmapInfo.bmiHeader, 0, sizeof(BitmapInfo.bmiHeader));
BitmapInfo.bmiHeader.biWidth = lv_bmp_width;
BitmapInfo.bmiHeader.biHeight = lv_bmp_height;
BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
BitmapInfo.bmiHeader.biPlanes = 1;
BitmapInfo.bmiHeader.biBitCount = 32;
BitmapInfo.bmiHeader.biCompression = BI_RGB;
hbmp = CreateDIBSection(dc_o, &BitmapInfo, DIB_RGB_COLORS, (void **)&Data, 0, 0);
HBITMAP old = (HBITMAP)SelectObject(dc, hbmp);
SetStretchBltMode(dc, HALFTONE);
StretchBlt(dc, 0, 0, lv_bmp_width, lv_bmp_height, dc_o, 0, 0, bm_o.bmWidth, bm_o.bmHeight, SRCCOPY);
SelectObject(dc_o, old_o);
hbmp = (HBITMAP)SelectObject(dc, old);
BITMAP bm = { 0 };
GetObject(hbmp, sizeof(bm), &bm);
hImageList_small = ImageList_Create(lv_bmp_width, lv_bmp_height, ILC_COLOR32 | ILC_MASK, 3, 0);
ImageList_Add(hImageList_small, hbmp, (HBITMAP)NULL);
ListView_SetImageList(hWndListView, hImageList_small, LVSIL_NORMAL);
LVITEM lv;
lv = { LVIF_IMAGE, itm_count, 0, 0, 0, NULL, 0, img_count, 0, 0, 0, 0, 0 };
ListView_InsertItem(hWndListView, &lv); img_count++; itm_count++;
hwndNextViewer = SetClipboardViewer(hwnd);
break;
}
/*********************************************************************************************/
case WM_DRAWCLIPBOARD:{
static UINT auPriorityList[] = {
CF_OWNERDISPLAY,
CF_TEXT,
CF_OEMTEXT,
CF_UNICODETEXT,
CF_ENHMETAFILE,
CF_BITMAP,
CF_DIB
};
if (!OpenClipboard(hwnd)) lasterror(L"Clipboard not opening");
UINT uformat = GetPriorityClipboardFormat(auPriorityList, 7);
HGLOBAL hnd;
LPWSTR wstr = NULL;
LPWSTR str = NULL;
switch (uformat)
{
case CF_OEMTEXT:
case CF_TEXT:
case CF_UNICODETEXT:{
if((hnd = GetClipboardData(CF_UNICODETEXT)) == NULL) lasterror(L"hbmp_o is NULL");
wstr = (LPWSTR)GlobalLock(hnd);
str = (LPWSTR)malloc(wcslen(wstr) * sizeof(WCHAR) + sizeof(WCHAR));
wcscpy(str, wstr);
GlobalUnlock(hnd);//GlobalFree(hnd); fuck global free. makes crash
CloseClipboard();
LVITEM lv;
lv = { LVIF_TEXT, itm_count++, 0, 0, 0, str, 0, 0, 0, 0, 0, 0, 0 };
int a = ListView_InsertItem(hWndListView, &lv); itm_count++;
free(str);
break;
}
//etc..
Aside from dropping the image list and custom drawing the bitmap into it, I have no solutions to this.
Related
I am using the following code to take a screenshot in C on Windows (from https://learn.microsoft.com/en-us/windows/win32/gdi/capturing-an-image).
int captureImage(HWND hWnd, char * filename){
HDC hdcScreen;
HDC hdcWindow;
HDC hdcMemDC = NULL;
HBITMAP hbmScreen = NULL;
BITMAP bmpScreen;
DWORD dwBytesWritten = 0;
DWORD dwSizeofDIB = 0;
HANDLE hFile = NULL;
char* lpbitmap = NULL;
HANDLE hDIB = NULL;
DWORD dwBmpSize = 0;
// retrieve handle to display device content
hdcScreen = GetDC(NULL);
hdcWindow = GetDC(hWnd);
// Create a compatible DC (domain controller)
hdcMemDC = CreateCompatibleDC(hdcWindow);
if (!hdcMemDC){
printf("Error creating hdcMemDC\n");
return 1;
}
// Make process DPI aware to avoid wrongly sized screenshots when screen resolution changes
SetProcessDPIAware();
// get area for size calculations
RECT rcClient;
GetClientRect(hWnd, &rcClient);
// use this stretch mode
SetStretchBltMode(hdcWindow, HALFTONE);
// the source DC is the entire screen, and the destination in the current window (for now)
StretchBlt(hdcWindow, 0, 0, rcClient.right, rcClient.bottom, hdcScreen, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), SRCCOPY);
// create a compatible bitmap from the Window DC
hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top);
if (!hbmScreen){
printf("Error creating hmbScreen\n");
return 1;
}
// Select the compatible bitmap into the memory DC
SelectObject(hdcMemDC, hbmScreen);
// transfer bits into the memory DC
BitBlt(hdcMemDC, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, hdcWindow, 0 , 0, SRCCOPY);
// get the bitmap from the hbitmap
GetObject(hbmScreen, sizeof(BITMAP), &bmpScreen);
// bitmap file header and info header
BITMAPFILEHEADER bmfHeader;
BITMAPINFOHEADER bi;
// set all values for info header
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;
dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount+31) / 32) * 4 * bmpScreen.bmHeight;
hDIB = GlobalAlloc(GHND, dwBmpSize);
lpbitmap = (char*)GlobalLock(hDIB);
// get the bits from the bitmap and copy them into the buffer
GetDIBits(hdcWindow, hbmScreen, 0, (UINT)bmpScreen.bmHeight, lpbitmap, (BITMAPINFO*)&bi, DIB_RGB_COLORS);
// create a file to save the capture into
hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
// get the total size of the file
dwSizeofDIB = dwBmpSize + (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
// offset to where our bitmap actually starts
bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
// size of the file
bmfHeader.bfSize = dwSizeofDIB;
// always set bfType to BM for bitmaps
bmfHeader.bfType = 0x4D42; // that's BM
// write data to the file
WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);
// unlock and free stuff
GlobalUnlock(hDIB);
GlobalFree(hDIB);
// close file handle
CloseHandle(hFile);
// Clean everything up
DeleteObject(hbmScreen);
DeleteObject(hdcMemDC);
ReleaseDC(NULL, hdcScreen);
ReleaseDC(hWnd, hdcWindow);
return 0; // for normal exit
}
Passing in the return value of GetDesktopWindow() will take a screenshot of the entire screen and save it a to a file with filename. The screenshot is the size of and has the resolution of the screen. So, if used on a 4k screen, that will be the resolution of the screenshot. I was wondering what the best way was to cap this at, say, 1080p. So even if the resolution is greater than 1080x1920, the screenshot will not go higher.
use such code
ULONG captureImage(_In_ ULONG cx, _In_ PCWSTR filename)
{
struct BMEX
{
USHORT ForAlign;
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;
UCHAR Bits[];
};
ULONG cxScreen = GetSystemMetrics(SM_CXSCREEN), cyScreen = GetSystemMetrics(SM_CYSCREEN);
ULONG cy = cyScreen * cx / cxScreen;
ULONG size = ((3 * cx + sizeof(ULONG) - 1) & ~(sizeof(ULONG) - 1)) * cy;
ULONG dwError;
if (HANDLE hSection = CreateFileMappingW(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, size + sizeof(BMEX), 0))
{
BITMAPINFO bi = {
{ sizeof(BITMAPINFOHEADER), cx, cy, 1, 24, BI_RGB, size }
};
PVOID Bits;
if (HBITMAP hbmp = CreateDIBSection(0, &bi, DIB_RGB_COLORS, &Bits, hSection, __builtin_offsetof(BMEX, Bits)))
{
if (HDC hdc = GetDC(0))
{
if (HDC hMemDC = CreateCompatibleDC(0))
{
HGDIOBJ h = SelectObject(hMemDC, hbmp);
if (StretchBlt(hMemDC, 0, 0, cx, cy, hdc, 0, 0, cxScreen, cyScreen, SRCCOPY))
{
HANDLE hFile = CreateFileW(filename, FILE_APPEND_DATA, 0, 0, CREATE_ALWAYS, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
BMEX* p = CONTAINING_RECORD(Bits, BMEX, Bits);
p->bfh.bfType = 'MB';
p->bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
p->bfh.bfSize = size += sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
p->bfh.bfReserved1 = 0;
p->bfh.bfReserved2 = 0;
memcpy(&p->bih, &bi.bmiHeader, sizeof(BITMAPINFOHEADER));
dwError = WriteFile(hFile, &p->bfh, size, &size, 0) ? NOERROR : GetLastError();
CloseHandle(hFile);
}
else
{
dwError = GetLastError();
}
}
else
{
dwError = GetLastError();
}
SelectObject(hMemDC, h);
DeleteDC(hMemDC);
}
else
{
dwError = GetLastError();
}
ReleaseDC(0, hdc);
}
else
{
dwError = GetLastError();
}
DeleteObject(hbmp);
}
else
{
dwError = GetLastError();
}
CloseHandle(hSection);
return dwError;
}
return GetLastError();
}
I am trying to create an OpenGL context with the ARB extention. I read lots of documentations, posts and the khronos wiki about that. But i can't make the final context current, as you see in the code, the second wglMakeCurrent() call is commented out, which means that the context that is acctualy used is the first one created, without the extention. If I uncomment that, the window doesn't displays.
I did some error testing with the ARB functions, it seems that the problem comes from the attribute list or the wglChoosePixelFormatARB() call.
The code :
#include <stdio.h>
#define UNICODE
#include <windows.h>
#include <dwmapi.h>
#define GLEW_STATIC
#include <glew.h>
#include <GL\wglext.h>
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp);
unsigned int CreateShaderProgram(char* VertexSource, char* FragmentSource);
int main(void){
WNDCLASSEX wcx = {};
wcx.cbSize = sizeof(WNDCLASSEX);
wcx.style = CS_OWNDC;
wcx.lpfnWndProc = WindowProcedure;
wcx.lpszClassName = L"Win32Class";
RegisterClassEx(&wcx);
HWND hWnd = CreateWindowEx(WS_EX_APPWINDOW | WS_EX_LAYERED, wcx.lpszClassName, L"Title",
WS_POPUP, 400, 300, 800, 400, NULL, NULL, NULL, NULL);
DWM_BLURBEHIND blur = {};
blur.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
blur.fEnable = 1;
blur.hRgnBlur = CreateRectRgn(0, 0, -1, -1);
DwmEnableBlurBehindWindow(hWnd, &blur);
SetLayeredWindowAttributes(hWnd, RGB(0, 0, 0), 255, LWA_COLORKEY);
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 = 32;
pfd.cDepthBits = 24;
pfd.cStencilBits = 8;
pfd.iLayerType = PFD_MAIN_PLANE;
HDC DeviceContext = GetDC(hWnd);
int PixelFormat = ChoosePixelFormat(DeviceContext, &pfd);
SetPixelFormat(DeviceContext, PixelFormat, &pfd);
HGLRC RenderingContext = wglCreateContext(DeviceContext);
wglMakeCurrent(DeviceContext, RenderingContext);
glewInit();
int Attributes[] = {
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,
WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
WGL_CONTEXT_MINOR_VERSION_ARB, 4,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
0,
};
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB =
wglGetProcAddress("wglChoosePixelFormatARB");
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB =
(PFNWGLCREATECONTEXTATTRIBSARBPROC)
wglGetProcAddress("wglCreateContextAttribsARB");
wglChoosePixelFormatARB(DeviceContext, Attributes, NULL, 1, &PixelFormat,
NULL);
SetPixelFormat(DeviceContext, PixelFormat, &pfd);
RenderingContext = wglCreateContextAttribsARB(DeviceContext, NULL,
Attributes);
//wglMakeCurrent(DeviceContext, RenderingContext);
char VertexShaderSource[] =
"#version 440 core\n"
"\n"
"layout(location = 0) in vec4 position;\n"
"\n"
"void main(){\n"
" gl_Position = position;\n"
"}";
char FragmentShaderSource[] =
"#version 440 core\n"
"\n"
"layout(location = 0) out vec4 colour;\n"
"\n"
"void main(){\n"
" colour = vec4(0.5, 0.5, 0.5, 1.0);\n"
"}";
float Verticies[] = {
0.0f, 0.5f, // top : 0
0.5f, 0.0f, // right : 1
0.0f, -0.5f, // bottom : 2
-0.5f, 0.0f // left : 3
};
unsigned int Indices[] = {
3, 0, 1, // top
3, 2, 1 // bottom
};
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
unsigned int VertexArray;
glGenVertexArrays(1, &VertexArray);
glBindVertexArray(VertexArray);
unsigned int VertexBuffer;
glGenBuffers(1, &VertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), Verticies, GL_STATIC_DRAW);
unsigned int IndexBuffer;
glGenBuffers(1, &IndexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), Indices,
GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
unsigned int ShaderProgram = CreateShaderProgram(VertexShaderSource,
FragmentShaderSource);
glUseProgram(ShaderProgram);
glViewport(0, 0, 800, 400);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
ShowWindow(hWnd, 1);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0)){
DispatchMessage(&msg);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL);
wglSwapLayerBuffers(DeviceContext, WGL_SWAP_MAIN_PLANE);
}
}
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp){
switch(uMsg){
case WM_NCHITTEST: return HTCAPTION;
case WM_DESTROY: PostQuitMessage(0); return 0;
default: return DefWindowProc(hWnd, uMsg, wp, lp);
}
}
unsigned int CreateShader(char* Source, unsigned int Type);
unsigned int CreateShaderProgram(char* VertexSource,
char* FragmentSource){
unsigned int ShaderProgram = glCreateProgram(),
VertexShader = CreateShader(VertexSource, GL_VERTEX_SHADER),
FragmentShader = CreateShader(FragmentSource, GL_FRAGMENT_SHADER);
glAttachShader(ShaderProgram, VertexShader);
glAttachShader(ShaderProgram, FragmentShader);
glLinkProgram(ShaderProgram);
glValidateProgram(ShaderProgram);
return ShaderProgram;
}
unsigned int CreateShader(char* Source, unsigned int Type){
unsigned int Shader = glCreateShader(Type);
glShaderSource(Shader, 1, (const char* const*)&Source, NULL);
glCompileShader(Shader);
return Shader;
}
Note : The cast of the result of the second call to wglGetProcAdress() produces a warning if the -Wextra flag is set ( for the gcc compiler ). I don't know how to fix it.
Update : This still not works : "Choosing the final window pixel format failed." and "Creating the final rendering context failed." are printed (see the code) below. And the window does not displays.
The new code : (the big comment is the old code) :
#include <stdio.h>
#define UNICODE
#include <windows.h>
#include <dwmapi.h>
#define GLEW_STATIC
#include <glew.h>
#include <GL\wglext.h>
LRESULT CALLBACK FirstWindowProcedure(HWND hWnd, UINT uMsg, WPARAM wp,
LPARAM lp);
LRESULT CALLBACK FinalWindowProcedure(HWND hWnd, UINT uMsg, WPARAM wp,
LPARAM lp);
unsigned int CreateShaderProgram(char* VertexSource, char* FragmentSource);
int main(void){
WNDCLASSEX FirstWindowClass = {};
FirstWindowClass.cbSize = sizeof(WNDCLASSEX);
FirstWindowClass.style = CS_OWNDC;
FirstWindowClass.lpfnWndProc = FirstWindowProcedure;
FirstWindowClass.lpszClassName = L"FirstWindowClass";
if(!RegisterClassEx(&FirstWindowClass))
puts("Registration of the first window class failed.\n");
HWND FirstWindow = CreateWindowEx(WS_EX_APPWINDOW,
FirstWindowClass.lpszClassName, L"FirstWindow", WS_POPUP, 0, 0, 10, 10,
NULL, NULL, NULL, NULL);
if(FirstWindow == NULL)
puts("Creation of the first window failed.\n");
PIXELFORMATDESCRIPTOR FirstWindowPixelFormatDescriptor = {};
FirstWindowPixelFormatDescriptor.nSize = sizeof(PIXELFORMATDESCRIPTOR);
FirstWindowPixelFormatDescriptor.nVersion = 1;
FirstWindowPixelFormatDescriptor.dwFlags = PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
FirstWindowPixelFormatDescriptor.iPixelType = PFD_TYPE_RGBA;
FirstWindowPixelFormatDescriptor.cColorBits = 32;
FirstWindowPixelFormatDescriptor.cDepthBits = 24;
FirstWindowPixelFormatDescriptor.cStencilBits = 8;
FirstWindowPixelFormatDescriptor.iLayerType = PFD_MAIN_PLANE;
HDC FirstWindowDeviceContext = GetDC(FirstWindow);
if(FirstWindowDeviceContext == NULL)
puts("First window device context retrieving failed.\n");
int FirstWindowPixelFormat = ChoosePixelFormat(FirstWindowDeviceContext,
&FirstWindowPixelFormatDescriptor);
if(FirstWindowPixelFormat == 0)
puts("Choosing the first pixel format failed.\n");
if(SetPixelFormat(FirstWindowDeviceContext, FirstWindowPixelFormat,
&FirstWindowPixelFormatDescriptor) == FALSE)
puts("Setting the first pixel format failed.\n");
HGLRC FirstWindowRenderingContext =
wglCreateContext(FirstWindowDeviceContext);
if(FirstWindowRenderingContext == NULL)
puts("Creating the first rendering context failed.\n");
if(wglMakeCurrent(FirstWindowDeviceContext, FirstWindowRenderingContext) ==
FALSE)
puts("Making the first context current failed.\n");
if(glewInit() != GLEW_OK)
puts("Initialisation of GLEW failed.\n");
WNDCLASSEX FinalWindowClass = {};
FinalWindowClass.cbSize = sizeof(WNDCLASSEX);
FinalWindowClass.style = CS_OWNDC;
FinalWindowClass.lpfnWndProc = FinalWindowProcedure;
FinalWindowClass.lpszClassName = L"FinalWindowClass";
if(!RegisterClassEx(&FinalWindowClass))
puts("Registration of the final window class failed\n");
HWND FinalWindow = CreateWindowEx(WS_EX_APPWINDOW,
FinalWindowClass.lpszClassName, L"FinalWindow", WS_POPUP, 0, 0, 10, 10,
NULL, NULL, NULL, NULL);
if(FinalWindow == NULL)
puts("Creation of the final window failed.\n");
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB =
wglGetProcAddress("wglChoosePixelFormatARB");
if(wglChoosePixelFormatARB == NULL)
puts("Getting the wglChoosePixelFormatARB function pointer failed.\n");
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB =
(PFNWGLCREATECONTEXTATTRIBSARBPROC)
wglGetProcAddress("wglCreateContextAttribsARB");
if(wglCreateContextAttribsARB == NULL)
puts("Getting the wglCreateContextAttribsARB function pointer"
"failed.\n");
int FinalWindowContextAttributes[] = {
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,
WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
WGL_CONTEXT_MINOR_VERSION_ARB, 4,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
0,
};
HDC FinalWindowDeviceContext = GetDC(FinalWindow);
if(FinalWindowDeviceContext == NULL)
puts("Retrieving the final window device cotext failed.\n");
int FinalWindowPixelFormat;
if(FALSE == wglChoosePixelFormatARB(FinalWindowDeviceContext,
FinalWindowContextAttributes, NULL, 1, &FinalWindowPixelFormat, NULL))
puts("Choosing the final window pixel format failed.\n");
HGLRC FinalWindowRenderingContext =
wglCreateContextAttribsARB(FinalWindowDeviceContext, NULL,
FinalWindowContextAttributes);
if(FinalWindowRenderingContext == NULL)
puts("Creating the final rendering context failed.\n");
if(FALSE == wglMakeCurrent(FinalWindowDeviceContext,
FinalWindowRenderingContext))
puts("Making the final context current failed.\n");
DWM_BLURBEHIND blur = {};
blur.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
blur.fEnable = 1;
blur.hRgnBlur = CreateRectRgn(0, 0, -1, -1);
DwmEnableBlurBehindWindow(FinalWindow, &blur);
SetLayeredWindowAttributes(FinalWindow, RGB(0, 0, 0), 255, LWA_COLORKEY);
// ----- ----- ----- //
/*WNDCLASSEX wcx = {};
wcx.cbSize = sizeof(WNDCLASSEX);
wcx.style = CS_OWNDC;
wcx.lpfnWndProc = WindowProcedure;
wcx.lpszClassName = L"Win32Class";
RegisterClassEx(&wcx);
HWND hWnd = CreateWindowEx(WS_EX_APPWINDOW | WS_EX_LAYERED, wcx.lpszClassName, L"Title",
WS_POPUP, 400, 300, 800, 400, NULL, NULL, NULL, NULL);
DWM_BLURBEHIND blur = {};
blur.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
blur.fEnable = 1;
blur.hRgnBlur = CreateRectRgn(0, 0, -1, -1);
DwmEnableBlurBehindWindow(hWnd, &blur);
SetLayeredWindowAttributes(hWnd, RGB(0, 0, 0), 255, LWA_COLORKEY);
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 = 32;
pfd.cDepthBits = 24;
pfd.cStencilBits = 8;
pfd.iLayerType = PFD_MAIN_PLANE;
HDC DeviceContext = GetDC(hWnd);
int PixelFormat = ChoosePixelFormat(DeviceContext, &pfd);
SetPixelFormat(DeviceContext, PixelFormat, &pfd);
HGLRC RenderingContext = wglCreateContext(DeviceContext);
wglMakeCurrent(DeviceContext, RenderingContext);
glewInit();
int Attributes[] = {
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,
WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
WGL_CONTEXT_MINOR_VERSION_ARB, 4,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
0,
};
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB =
wglGetProcAddress("wglChoosePixelFormatARB");
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB =
(PFNWGLCREATECONTEXTATTRIBSARBPROC)
wglGetProcAddress("wglCreateContextAttribsARB");
wglChoosePixelFormatARB(DeviceContext, Attributes, NULL, 1, &PixelFormat,
NULL);
RenderingContext = wglCreateContextAttribsARB(DeviceContext, NULL,
Attributes);
wglMakeCurrent(DeviceContext, RenderingContext);*/
char VertexShaderSource[] =
"#version 440 core\n"
"\n"
"layout(location = 0) in vec4 position;\n"
"\n"
"void main(){\n"
" gl_Position = position;\n"
"}";
char FragmentShaderSource[] =
"#version 440 core\n"
"\n"
"layout(location = 0) out vec4 colour;\n"
"\n"
"void main(){\n"
" colour = vec4(0.5, 0.5, 0.5, 1.0);\n"
"}";
float Verticies[] = {
0.0f, 0.5f, // top : 0
0.5f, 0.0f, // right : 1
0.0f, -0.5f, // bottom : 2
-0.5f, 0.0f // left : 3
};
unsigned int Indices[] = {
3, 0, 1, // top
3, 2, 1 // bottom
};
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
unsigned int VertexArray;
glGenVertexArrays(1, &VertexArray);
glBindVertexArray(VertexArray);
unsigned int VertexBuffer;
glGenBuffers(1, &VertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), Verticies, GL_STATIC_DRAW);
unsigned int IndexBuffer;
glGenBuffers(1, &IndexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), Indices,
GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
unsigned int ShaderProgram = CreateShaderProgram(VertexShaderSource,
FragmentShaderSource);
glUseProgram(ShaderProgram);
glViewport(0, 0, 800, 400);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
ShowWindow(FinalWindow, 1);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0)){
DispatchMessage(&msg);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL);
wglSwapLayerBuffers(FinalWindowDeviceContext, WGL_SWAP_MAIN_PLANE);
}
}
LRESULT CALLBACK FirstWindowProcedure(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp){
return DefWindowProc(hWnd, uMsg, wp, lp);
}
LRESULT CALLBACK FinalWindowProcedure(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp){
switch(uMsg){
case WM_NCHITTEST: return HTCAPTION;
case WM_DESTROY: PostQuitMessage(0); return 0;
default: return DefWindowProc(hWnd, uMsg, wp, lp);
}
}
unsigned int CreateShader(char* Source, unsigned int Type);
unsigned int CreateShaderProgram(char* VertexSource,
char* FragmentSource){
unsigned int ShaderProgram = glCreateProgram(),
VertexShader = CreateShader(VertexSource, GL_VERTEX_SHADER),
FragmentShader = CreateShader(FragmentSource, GL_FRAGMENT_SHADER);
glAttachShader(ShaderProgram, VertexShader);
glAttachShader(ShaderProgram, FragmentShader);
glLinkProgram(ShaderProgram);
glValidateProgram(ShaderProgram);
return ShaderProgram;
}
unsigned int CreateShader(char* Source, unsigned int Type){
unsigned int Shader = glCreateShader(Type);
glShaderSource(Shader, 1, (const char* const*)&Source, NULL);
glCompileShader(Shader);
return Shader;
}
SetPixelFormat(DeviceContext, PixelFormat, &pfd);
You can't do SetPixelFormat() twice for the same window - this is described in WinAPI documentation and elaborated in every article describing usage of wglChoosePixelFormatARB/wglCreateContextAttribsARB on Windows platform that I've seen:
Once a window's pixel format is set, it cannot be changed.
The only way is creating a temporary OpenGL context on temporary window and then making an OpenGL context for a final window.
Add verbose checks to your code to see where it fails - don't ignore NULL checks and BOOL results of WinAPI functions.
So I've been trying to add images to my WinAPI TreeView Common Control items. However, I have encountered something that has really been bothering me and I have no clue why it is happening. For some reason, the Image in a TreeView has a different color than the actual bitmap does. I took a screenshot of a test program I made that paints a BMP image file along with its TreeView counterpart. (It is the exact same image yet both drawings yield different results).
As you can see the image on the left is what it should look like and the image on the right is what the TreeView is drawing. Is this just the way TreeView works or something? Or is there something in my code that I'm doing wrong? It would be much appreciated if anyone could point this out because out of personal taste, the TreeView image looks visually disgusting and I would like the TreeView Control to draw my image correctly :P
The following is the code I am using to create the Treeview:
//Load image from relative file path
g_hBmp = LoadImage(GetModuleHandle(NULL), "image.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE);
//Create Treeview
HWND treeview = CreateWindowEx(0, WC_TREEVIEW, NULL,
WS_VISIBLE | WS_CHILD | TVS_FULLROWSELECT,
250, 100, 500, 300,
hwnd, NULL, GetModuleHandle(NULL), NULL);
//Add single treeview item
TVITEM tvi = {0};
TVINSERTSTRUCT tvins = {0};
HIMAGELIST himl = NULL;
himl = ImageList_Create(90, 90, 0, 1, 0);
int image = ImageList_Add(himl, g_hBmp, NULL);
SendMessage(treeview, TVM_SETIMAGELIST, (WPARAM) TVSIL_NORMAL, (LPARAM) himl);
tvi.mask = TVIF_TEXT | TVIF_IMAGE;
//Set Text
tvi.pszText = "Some Item";
tvi.cchTextMax = sizeof("Some Item") - 1;
tvi.iImage = image;
tvins.item = tvi;
tvins.hInsertAfter = TVI_FIRST;
SendMessage(treeview, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT) &tvins);
And here is my entire code in case you want to copy it:
#include <windows.h>
#include <commctrl.h>
HBITMAP g_hBmp = NULL;
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CREATE: {
//Load Image
g_hBmp = LoadImage(GetModuleHandle(NULL), "image.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE);
//Create Treeview
HWND treeview = CreateWindowEx(0, WC_TREEVIEW, NULL,
WS_VISIBLE | WS_CHILD | TVS_FULLROWSELECT,
250, 100, 500, 300,
hwnd, NULL, GetModuleHandle(NULL), NULL);
//Add single treeview item
TVITEM tvi = {0};
TVINSERTSTRUCT tvins = {0};
HIMAGELIST himl = NULL;
himl = ImageList_Create(90, 90, 0, 1, 0);
int image = ImageList_Add(himl, g_hBmp, NULL);
SendMessage(treeview, TVM_SETIMAGELIST, (WPARAM) TVSIL_NORMAL, (LPARAM) himl);
tvi.mask = TVIF_TEXT | TVIF_IMAGE;
//Set Text
tvi.pszText = "Some Item";
tvi.cchTextMax = sizeof("Some Item") - 1;
tvi.iImage = image;
tvins.item = tvi;
tvins.hInsertAfter = TVI_FIRST;
SendMessage(treeview, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT) &tvins);
break;
}
case WM_PAINT: {
PAINTSTRUCT ps = {0};
//Setup
HDC hdc = BeginPaint(hwnd, &ps);
HDC hdcPaint = CreateCompatibleDC(hdc);
HBITMAP hBmpOld = (HBITMAP) SelectObject(hdcPaint, g_hBmp);
//Painting
BitBlt(hdc, 100, 100, 90, 90, hdcPaint, 0, 0, SRCCOPY);
//Cleanup
SelectObject(hdcPaint, hBmpOld);
DeleteDC(hdcPaint);
EndPaint(hwnd, &ps);
break;
}
case WM_DESTROY: {
DeleteObject(g_hBmp);
PostQuitMessage(0);
break;
}
default: return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
InitCommonControls();
HWND hwnd = NULL;
WNDCLASSEX wc = {0};
wc.cbSize = sizeof(WNDCLASSEX);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wc.hInstance = hInstance;
wc.hbrBackground = (HBRUSH) COLOR_WINDOW;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Parent Window";
wc.style = CS_VREDRAW | CS_HREDRAW;
RegisterClassEx(&wc);
hwnd = CreateWindowEx(0, wc.lpszClassName, "Render Window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 1000, 1000 / 16 * 9,
NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, nShowCmd);
UpdateWindow(hwnd);
MSG msg = {0};
while (GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
As mentioned above by 'Swordfish', what I was missing was the proper flag when calling the ImageList_Create() function. As you can see in my call to ImageList_Create(90, 90, 0, 1, 0); I specify '0' as the third parameter (which represents the Image List Creation Flag). As stated in the documentation, the ILC_COLOR flag has a value of zero; when this flag is set it uses the 'default behavior' which is often ILC_COLOR4 (i.e. 4 bits per channel).
To fix this all I needed to do was simply call the function using the ILC_COLOR24 flag, indicating that my images have a 24-bit depth.
ImageList_Create(90, 90, ILC_COLOR24, 1, 0);
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'm using C - (NO MFC or GDI+) :-)
What I want is to set the opacity of my child window to let say 100 (my child window is a STATIC control). I was wondering if this is even possible and if so can someone please point me to the right direction on how to do it.
Here is my setup:
I create my Parent window as follow:
HWND hWnd;
WNDCLASS wndCls_s;
wndCls_s.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wndCls_s.lpfnWndProc = MainWndProc;
wndCls_s.cbClsExtra = 0;
wndCls_s.cbWndExtra = 0;
wndCls_s.hInstance = hInstance;
wndCls_s.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_BSN_64));
wndCls_s.hCursor = LoadCursor(NULL, IDC_ARROW);
wndCls_s.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));
wndCls_s.lpszMenuName = NULL;
wndCls_s.lpszClassName = pszCName;
if (RegisterClass(&wndCls_s) == 0)
return EXIT_FAILURE;
/* Creating Window */
hWnd = CreateWindow(
pszCName, pszCName,
WS_VISIBLE | WS_POPUP | WS_SYSMENU | WS_CLIPCHILDREN,
0, 0, WND_WIDTH, WND_HEIGHT,
NULL, NULL, hInstance, NULL);
In my MainWndProc:
case WM_CREATE:
{
HWND hWndChild = CreateWindow(
L"STATIC", (LPCTSTR) NULL,
WS_CHILD | WS_VISIBLE,
10, 10, 110, 110,
hWnd, (HMENU) (int) 10000,
g_hInst, NULL);
}
break;
case WM_CTLCOLORSTATIC:
{
COLORREF dwColor;
dwColor = RGB(255, 0, 0);
hDC = (HDC) wParam;
//SetBkColor(hDC, dwColor);
SetBkMode(hDC, TRANSPARENT);
/*
This is not going to work for child window
SetWindowLong(
hWnd, GWL_EXSTYLE,
GetWindowLong((HWND)lParam, GWL_EXSTYLE) & ~WS_EX_LAYERED);
SetLayeredWindowAttributes(
(HWND)lParam, 0, 100, LWA_ALPHA);
RedrawWindow((HWND)lParam, NULL, NULL, RDW_ERASE | RDW_INVALIDATE);
*/
if (g_hBrushRed == NULL)
g_hBrushRed = CreateSolidBrush(dwColor);
}
return (INT_PTR)g_hBrushRed;
Why do you enable transparency with TRANSPARENT if you are going to return a valid brush for the background? You don't need SetBkMode and your red brush will be used by the control then.