Void to HBITMAP conversion Issue - c

I keep getting an error at line 123:
123 C:\Dev-Cpp\Window_main_2.c invalid conversion from `void*' to `HBITMAP__*'
I don't know what to make of this and its driving me crazy.
void DrawBitmap(HDC hdcDest, char *filename, int x, int y)
{
HBITMAP image;
BITMAP bm;
HDC hdcMem;
// This is the line that brings about the issue (just ask me if more code is required because
// there is a lot more. Essentially this whole function points to a file and I call this
// function in another function that will compile a windows screen filled with the following
// image path. But I cant get this HBITMAP to agree with the image datatype. Please let me
// know if more info is required and thank you.) The line is below.
image = LoadImage(0, "C:\\Users\\Lillian\\Pictures\\c.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
GetObject(image, sizeof(BITMAP), &bm);
hdcMem = CreateCompatibleDC(global_hdc);
SelectObject(hdcMem, image);
BitBlt(
global_hdc,
x,
y,
bm.bmWidth,
bm.bmHeight,
hdcMem,
0,
0,
SRCCOPY);
DeleteDC(hdcMem);
DeleteObject((HBITMAP)image);
}

LoadImage() returns a HANDLE. Your need a cast when assigning the result to your variable:
image = (HBITMAP) LoadImage(0, "C:\\Users\\Lillian\\Pictures\\c.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
Also, before you DeleteDC(), you need to select the original HBITMAP back into hdcMem - you need to save it when you call SelectObject() earlier.

Related

wglCreateContext fails with error "The pixel format is invalid"

I'm trying to access the entire screen with the context.
Here's my current code (currently only this file):
#include <stdio.h>
#include <Windows.h>
#include <GL/gl.h>
#include <gl/glu.h>
#include <GL/glext.h>
int main(int argc, char *argv[]) {
HDC hdc = GetDC(NULL);
HGLRC hglrc;
hglrc = wglCreateContext(hdc);
// Handle errors
if (hglrc == NULL) {
DWORD errorCode = GetLastError();
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
errorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0, NULL );
printf("Failed with error %d: %s", errorCode, lpMsgBuf);
LocalFree(lpMsgBuf);
ExitProcess(errorCode);
}
wglMakeCurrent(hdc, hglrc);
printf("%s\n", (char) glGetString(GL_VENDOR));
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hglrc);
return 0;
}
The problem is in this code at the start:
HDC hdc = GetDC(NULL);
HGLRC hglrc;
hglrc = wglCreateContext(hdc);
and the program's output (printed in the error handling if statement) is
Failed with error 2000: The pixel format is invalid.
Calling GetDC(NULL) is specified as retrieving the DC of the entire screen, so I'm not sure what is going wrong here. How do I fix this?
EDIT: added more information
You didn't set the pixel format.
Have a look at the documentation here.
You should declare a pixel format descriptor, for example:
PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, // Flags
PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette.
32, // Colordepth of the framebuffer.
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
24, // Number of bits for the depthbuffer
8, // Number of bits for the stencilbuffer
0, // Number of Aux buffers in the framebuffer.
PFD_MAIN_PLANE,
0,
0, 0, 0
};
Then use the ChoosePixelFormat to obtain the pixel format number, e.g.:
int iPixelFormat = ChoosePixelFormat(hdc, &pfd);
and finally call the SetPixelFormat function to set the correct pixel format, e.g.:
SetPixelFormat(hdc, iPixelFormat, &pfd);
Only then, you can call the wglCreateContext function.
UPDATE
As pointed out by user Chris Becke one can not call SetPixelFormat on the screen hDC (obtained with GetDC(NULL) as per the OP code). This is reported also in the khronos wiki here.
Therefore, you must also create your own Window, obtain its DC and then use it to set the pixel format and create the GL context. If you want to render "fullscreen" you simply have to create a borderless window with the same size of the screen. I suggest to have a look at the answers to this old question here on SO about this matter.

HDC to HDC for HDC [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I would like to blit hdc to an other hdc, and this hdc will be blit into hdc containing "BeginPaint". But a problem appears, nothing have been drawn.
this is the code, thanks,
HDC hdcMem3 = CreateCompatibleDC(NULL);
SelectObject(hdcMem3, Picture);
BITMAP bitmap;
GetObject(Picture, sizeof(bitmap), &bitmap);
HDC hdcMem2 = CreateCompatibleDC(NULL);
BitBlt(hdcMem2, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hdcMem3, 0, 0, SRCCOPY);
DeleteDC(hdcMem3);
BitBlt(hdcMem, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hdcMem2, 0, 0, SRCCOPY);
DeleteDC(hdcMem2);
CreateCompatibleDC creates a device context with a 1-pixel monochrome bitmap.
In your example, the device context referenced by hdcMem3 has a real bitmap, but the DC referenced by hdcMem2 has only the 1-pixel monochrome bitmap. When you blit from hdcMem3 to hdcMem2, you probably end up with 1 black pixel.
What you need is to create a memory bitmap to select into hdcMem2. I assume that, eventually, you're going to display this in a window. Let's assume that you have a device context for the window called hdcWindow.
// Create a memory bitmap that's compatible with the window (screen) and
// the same size as Picture.
hbmpMem2 = CreateCompatibleBitmap(hdcWindow, bitmap.bmWidth, bitmap.bmHeight);
hbmpOld2 = SelectObject(hdcMem2, hbmpMem2);
Now when you do stuff to hdcMem2, it will draw to a real bitmap.
When you're done with hdcMem2, you need to first take care of hbmpMem2:
SelectObject(hdcMem2, hbmpOld2);
DeleteObject(hbmpMem2);
DestroyDC(hdcMem2);
Okay work ! but i've found one thing see :
BITMAP bitmap;
GetObject(picture, sizeof(bitmap), &bitmap);
LPBITMAPINFO Hbitmap = new BITMAPINFO;
Hbitmap->bmiHeader.biSize = sizeof(Hbitmap->bmiHeader);
Hbitmap->bmiHeader.biWidth = 300;
Hbitmap->bmiHeader.biHeight = 300;
Hbitmap->bmiHeader.biPlanes = 1;
Hbitmap->bmiHeader.biBitCount = 32;
Hbitmap->bmiHeader.biCompression = BI_RGB;
Hbitmap->bmiHeader.biSizeImage = 300 * 4 * 300;
Hbitmap->bmiHeader.biClrUsed = 0;
Hbitmap->bmiHeader.biClrImportant = 0;
HDC hdcMem3 = CreateCompatibleDC(NULL);
SelectObject(hdcMem3, picture);
HDC hdcMem2 = CreateCompatibleDC(NULL);
HBITMAP BhdcMem2 = CreateDIBSection(hdcMem2, Hbitmap, DIB_RGB_COLORS,0, 0, 0);
SelectObject(hdcMem2, BhdcMem2);
BitBlt(hdcMem2, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hdcMem3, 0, 0, SRCCOPY);
BitBlt(hdcMem, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hdcMem2, 0, 0, SRCCOPY);
DeleteDC(hdcMem2);
DeleteDC(hdcMem3);
delete Hbitmap;

How to create sprite animation using winapi c?

How to create sprite animation using winapi without gdi?
im trying to do this:
Sprite(hDC, L"fon.bmp",150, 14, 30, 30, SRCCOPY);
void Sprite(HDC hdc, CHAR* Path, int x, int y, int Width, int Height, DWORD rop)
{
HBITMAP bmp = (HBITMAP) LoadImage(NULL, Path, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
HDC memdc = CreateCompatibleDC(hdc);
SelectObject(memdc, bmp);
BitBlt(hdc, x, y, Width, Height, memdc, 0, 0, rop);
}
How i can change frame?
Create a vector and place frames of the animation. Then using some sort of timer, erase the screen and bitblt the next frame's image. This is common way of doing frame based animation and there is nothing specific for winapi.

Using GDI+ in C - gdiPlusStartup function returning 2

I am attempting to use GDI+ in my C application to take a screenshot and save it as JPEG. I am using GDI+ to convert the BMP to JPEG but apparently when calling the GdiplusStartup function, the return code is 2(invalid parameter) instead of 0:
int main()
{
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
//if(GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL) != 0)
// printf("GDI NOT WORKING\n");
printf("%d",GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL));
HDC hdc = GetDC(NULL); // get the desktop device context
HDC hDest = CreateCompatibleDC(hdc); // create a device context to use yourself
// get the height and width of the screen
int height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
int width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
// create a bitmap
HBITMAP hbDesktop = CreateCompatibleBitmap( hdc, width, height);
// use the previously created device context with the bitmap
SelectObject(hDest, hbDesktop);
// copy from the desktop device context to the bitmap device context
// call this once per 'frame'
BitBlt(hDest, 0,0, width, height, hdc, 0, 0, SRCCOPY);
// after the recording is done, release the desktop context you got..
ReleaseDC(NULL, hdc);
// ..and delete the context you created
DeleteDC(hDest);
SaveJpeg(hbDesktop,"a.jpeg",100);
GdiplusShutdown(gdiplusToken);
return 0;
}
I am trying to figure out why the GdiplusStartup function is not working.
Any thoughts?
Initialize gdiplusStartupInput variable with the following values: GdiplusVersion = 1, DebugEventCallback = NULL, SuppressBackgroundThread = FALSE, SuppressExternalCodecs = FALSE
According to MSDN article GdiplusStartup function http://msdn.microsoft.com/en-us/library/windows/desktop/ms534077%28v=vs.85%29.aspx
GdiplusStartupInput structure has default constructor which initializes the structure with these values. Since you call the function from C, constructor is not working and structure remains uninitialized. Provide your own initialization code to solve the problem.
// As Global
ULONG_PTR gdiplusToken;
// In top of main
GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup(&programInfo.gdiplusToken, &gdiplusStartupInput, NULL);
works for me.

WinAPI get mouse cursor icon

I want to get the cursor icon in Windows.
I think language I use isn't very important here, so I will just write pseudo code with WinAPI functions I'm trying to use:
c = CURSORINFO.new(20, 1, 1, POINT.new(1,1));
GetCursorInfo(c); #provides correctly filled structure with hCursor
DrawIcon(GetWindowDC(GetForegroundWindow()), 1, 1, c.hCursor);
So this part works fine, it draws current cursor on active window.
But that's not what I want. I want to get an array of pixels, so I should draw it in memory.
I'm trying to do it like this:
hdc = CreateCompatibleDC(GetDC(0)); #returns non-zero int
canvas = CreateCompatibleBitmap(hdc, 256, 256); #returns non-zero int too
c = CURSORINFO.new(20, 1, 1, POINT.new(1,1));
GetCursorInfo(c);
DrawIcon(hdc, 1, 1, c.hCursor); #returns 1
GetPixel(hdc, 1, 1); #returns -1
Why doesn't GetPixel() return COLORREF? What am I missing?
I'm not very experienced with WinAPI, so I'm probably doing some stupid mistake.
You have to select the bitmap you create into the device context. If not, the GetPixel function will return CLR_INVALID (0xFFFFFFFF):
A bitmap must be selected within the device context, otherwise, CLR_INVALID is returned on all pixels.
Also, the pseudo-code you've shown is leaking objects badly. Whenever you call GetDC, you must call ReleaseDC when you're finished using it. And whenever you create a GDI object, you must destroy it when you're finished using it.
Finally, you appear to be assuming that the coordinates for the point of origin—that is, the upper left point—are (1, 1). They are actually (0, 0).
Here's the code I would write (error checking omitted for brevity):
// Get your device contexts.
HDC hdcScreen = GetDC(NULL);
HDC hdcMem = CreateCompatibleDC(hdcScreen);
// Create the bitmap to use as a canvas.
HBITMAP hbmCanvas = CreateCompatibleBitmap(hdcScreen, 256, 256);
// Select the bitmap into the device context.
HGDIOBJ hbmOld = SelectObject(hdcMem, hbmCanvas);
// Get information about the global cursor.
CURSORINFO ci;
ci.cbSize = sizeof(ci);
GetCursorInfo(&ci);
// Draw the cursor into the canvas.
DrawIcon(hdcMem, 0, 0, ci.hCursor);
// Get the color of the pixel you're interested in.
COLORREF clr = GetPixel(hdcMem, 0, 0);
// Clean up after yourself.
SelectObject(hdcMem, hbmOld);
DeleteObject(hbmCanvas);
DeleteDC(hdcMem);
ReleaseDC(hdcScreen);
But one final caveat—the DrawIcon function will probably not work as you expect. It is limited to drawing an icon or cursor at the default size. On most systems, that will be 32x32. From the documentation:
DrawIcon draws the icon or cursor using the width and height specified by the system metric values for icons; for more information, see GetSystemMetrics.
Instead, you probably want to use the DrawIconEx function. The following code will draw the cursor at the actual size of the resource:
DrawIconEx(hdcMem, 0, 0, ci.hCursor, 0, 0, 0, NULL, DI_NORMAL);

Resources