how to send a bitmap to server? using C - c

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......

Related

Why can't I replace BeginPaint() with ValidateRect()?

From my understanding, BeginPaint and EndPaint helps paint the screen and validates the rectangle that it paints, this also prevents WM_PAINT messages from being spammed since there will be no more invalid regions in the window.
With my understanding, I thought that theoretically speaking, if I were to use BitBlt() to paint the window in WM_CREATE, then use ValidateRect to Validate the entire client region, the code would work. However, I tried it and it doesn't, suggesting that there could be something possibly wrong with my understanding, or code. Could someone please explain to me where I went wrong?
Here is the code that I used, IDB_BITMAP1 can be replaced with any appropriate Bitmap. Do note the comment in WM_PAINT to reproduce the issue. Thanks for reading!
#include <windows.h>
#include "resource.h"
HBITMAP hBitMap = NULL;
LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
{
BITMAP infoBM;
hBitMap = LoadBitmap(GetModuleHandle(NULL), IDB_BITMAP1);
if (hBitMap == NULL)
{
MessageBoxA(NULL, "COULD NOT LOAD CAT BITMAP", "ERROR", MB_OK);
}
HDC winDC = GetDC(hwnd);
HDC hMem = CreateCompatibleDC(winDC);
GetObject(hBitMap, sizeof(infoBM), &infoBM);
HBITMAP hMemOld = SelectObject(hMem, hBitMap);
BitBlt(winDC, 0, 0, infoBM.bmWidth, infoBM.bmHeight, hMem, 0, 0, SRCCOPY);
SelectObject(hMem, hMemOld);
DeleteDC(hMem);
ReleaseDC(hwnd,winDC);
break;
}
case WM_PAINT: //<<<--------- I replaced the entire segment here with ValidateRect(hwnd,NULL);break; And the whole window doesnt show anymore, why is that so?
{
BITMAP infoBM;
PAINTSTRUCT ps;
HDC winDC = BeginPaint(hwnd, &ps);
GetObject(hBitMap, sizeof(infoBM), &infoBM);
HDC hMem = CreateCompatibleDC(winDC);
HBITMAP hOldMem = SelectObject(hMem, hBitMap);
BitBlt(winDC, 0, 0, infoBM.bmWidth, infoBM.bmHeight, hMem, 0, 0, SRCCOPY);
SelectObject(hMem, hOldMem);
DeleteObject(hMem);
EndPaint(hwnd, &ps);
break;
}
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:return DefWindowProcA(hwnd, msg, wParam, lParam);
}
return 0;
}
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevIstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc = { sizeof(WNDCLASSEX),0,WindowProc,0,0,hInstance,NULL,LoadCursor(NULL,IDC_ARROW),(HBRUSH)(COLOR_WINDOW+1),NULL,"WindowClass",LoadIcon(NULL,IDI_APPLICATION)};
if (!RegisterClassEx(&wc))
{
MessageBoxA(NULL, "WINDOW REGISTRATION FAILED", "ERROR", MB_OK);
}
HWND hwnd = CreateWindowEx(WS_EX_LAYERED, "WindowClass", "Title", WS_POPUP, 200, 200, 300, 300, NULL, NULL, hInstance, NULL);
if (!hwnd)
{
MessageBoxA(NULL, "WINDOW CREATION FAILED", "ERROR", MB_OK);
}
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
if (!SetLayeredWindowAttributes(hwnd, RGB(0, 0, 0), 255, LWA_ALPHA))
{
MessageBoxA(NULL, "WINDOW LAYERED ATTRIBUTES FAILED", "ERROR", MB_OK);
}
MSG msg;
while (GetMessage(&msg, hwnd, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
Typically,
You use the GetDC function to carry out drawing that must occur
instantly rather than when a WM_PAINT message is
processing.
And if you'd like, you can ValidateRect the entire client area instead of real painting when a WM_PAINT message is processing.
The following code is adapted from the thread.
LRESULT CALLBACK MyWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static int i = 0;
switch (message)
{
case WM_PAINT:
{
if (i++ < 100)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
RECT rect;
GetClientRect(hWnd, &rect);
COLORREF clrbak = SetBkColor(hdc, RGB(255, 0, 0));
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
int x = (rect.right - rect.left) / 8;
int y = (rect.bottom - rect.top) / 8;
rect.left += x; rect.right -= x;
rect.top += y; rect.bottom -= y;
SetBkColor(hdc, RGB(0, 255, 0));
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
rect.left += x; rect.right -= x;
rect.top += y; rect.bottom -= y;
SetBkColor(hdc, RGB(0, 0, 255));
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
rect.left += x; rect.right -= x;
rect.top += y; rect.bottom -= y;
SetBkColor(hdc, RGB(0, 0, 0));
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
SetBkColor(hdc, clrbak);
EndPaint(hWnd, &ps);
}
else
{
ValidateRect(hWnd,NULL);
}
}
break;
case WM_ERASEBKGND:
return 1;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

How to take a screenshot with a maximum resolution in C

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 composed sending bitmap using C [duplicate]

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......

How to make a fade effect in WINAPI GDI?

Below I have a code snippet showing what I have tried.
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <windowsx.h>
#define WC_MAIN "MainClass"
#define WC_NUMBER "NumberClass"
LRESULT CALLBACK NumberProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
void InitClasses(void)
{
WNDCLASS wc;
memset(&wc, 0, sizeof(wc));
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpfnWndProc = MainWndProc;
wc.lpszClassName = WC_MAIN;
RegisterClass(&wc);
wc.lpfnWndProc = NumberProc;
wc.lpszClassName = WC_NUMBER;
RegisterClass(&wc);
}
#define NUMBER_SPEED 2
#define NUMBER_TICK_SPEED 25
#define NUMBER_TICKS 55
typedef struct {
UINT ticks;
HBITMAP buffer;
} NUMBERINFO;
HWND CreateNumber(HWND parent, const char *text, int x, int y, COLORREF color)
{
NUMBERINFO *ni = malloc(sizeof(*ni));
HDC hdc = GetDC(NULL);
HFONT oldFont = NULL;
SIZE s;
GetTextExtentPoint32(hdc, text, strlen(text), &s);
SelectObject(hdc, oldFont);
BITMAPINFO bmi;
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = s.cx;
bmi.bmiHeader.biHeight = s.cy;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32; // four 8-bit components
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = s.cx * s.cy * 4;
COLORREF *pvBits;
HBITMAP buffer = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, (void**) &pvBits, NULL, 0);
HDC bufferDc = CreateCompatibleDC(hdc);
HBITMAP oldBmp = SelectObject(bufferDc, buffer);
oldFont = NULL;
SetTextAlign(bufferDc, TA_TOP | TA_LEFT);
SetBkMode(bufferDc, TRANSPARENT);
SetTextColor(bufferDc, color);
TextOut(bufferDc, 0, 0, text, strlen(text));
SelectObject(bufferDc, oldFont);
SelectObject(bufferDc, oldBmp);
DeleteDC(bufferDc);
ReleaseDC(NULL, hdc);
ni->buffer = buffer;
return CreateWindow(WC_NUMBER, text, WS_VISIBLE | WS_CHILD, x - (s.cx >> 1), y - (s.cy >> 1), s.cx, s.cy, parent, NULL, NULL, ni);
}
LRESULT CALLBACK NumberProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
NUMBERINFO *info = (NUMBERINFO*) GetWindowLongPtr(hWnd, GWLP_USERDATA);
switch(msg)
{
case WM_CREATE:
info = ((CREATESTRUCT*) lParam)->lpCreateParams;
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) info);
SetTimer(hWnd, 0, NUMBER_TICK_SPEED, NULL);
info->ticks = NUMBER_TICKS;
return 0;
case WM_DESTROY: return 0;
case WM_TIMER:
{
RECT rc;
GetWindowRect(hWnd, &rc);
HWND parent = GetParent(hWnd);
MapWindowPoints(HWND_DESKTOP, parent, (POINT*) &rc, 2);
rc.top -= NUMBER_SPEED;
if(!--info->ticks)
{
DestroyWindow(hWnd);
return 0;
}
SetWindowPos(hWnd, NULL, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top - NUMBER_SPEED, SWP_NOREDRAW | SWP_NOCOPYBITS);
// redraw parent call erases last shown number
RedrawWindow(GetParent(hWnd), &rc, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW);
return 0;
}
case WM_ERASEBKGND: return 1;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
RECT r;
GetClientRect(hWnd, &r);
HDC bufferDc = CreateCompatibleDC(hdc);
HBITMAP oldBmp = SelectObject(bufferDc, info->buffer);
BLENDFUNCTION bfn;
bfn.BlendOp = AC_SRC_OVER;
bfn.BlendFlags = 0;
bfn.SourceConstantAlpha = info->ticks * 0xFF / NUMBER_TICKS;
bfn.AlphaFormat = 0;
//TransparentBlt(hdc, 0, 0, r.right, r.bottom, bufferDc, 0, 0, r.right, r.bottom, 0);
AlphaBlend(hdc, 0, 0, r.right, r.bottom, bufferDc, 0, 0, r.right, r.bottom, bfn);
SelectObject(bufferDc, oldBmp);
DeleteDC(bufferDc);
EndPaint(hWnd, &ps);
return 0;
}
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
LRESULT CALLBACK MainWndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_DESTROY: PostQuitMessage(0); return 0;
case WM_ERASEBKGND: return 1;
case WM_PAINT:
{
InvalidateRect(hWnd, NULL, FALSE);
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// draw gradient (red to green)
RECT r;
GetClientRect(hWnd, &r);
GRADIENT_RECT gr;
gr.UpperLeft = 0;
gr.LowerRight = 1;
TRIVERTEX pVertex[2] = {
{ 0, 0, 0xFF00, 0x0000, 0x0000, 0xFF00 },
{ r.right, r.bottom, 0x0000, 0xFF00, 0x0000, 0xFF00 }
};
GradientFill(hdc, pVertex, 2, &gr, 2, GRADIENT_FILL_RECT_H);
EndPaint(hWnd, &ps);
return 0;
}
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
int main()
{
InitClasses();
HWND mainWindow = CreateWindow(WC_MAIN, "Title", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, GetModuleHandle(NULL), NULL);
ShowWindow(mainWindow, 1);
UpdateWindow(mainWindow);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
// adding a number at mouse position if pressed (testing)
if(msg.message == WM_LBUTTONDOWN)
{
RECT r;
GetClientRect(mainWindow, &r);
int x = GET_X_LPARAM(msg.lParam);
int y = GET_Y_LPARAM(msg.lParam);
CreateNumber(mainWindow, "123", x, y, 0xFFFF00);
}
}
return 0;
}
This draws some text with any color and every time a timer ticks, the text becomes more faded (more transparent), but the black background of the bitmap the text was drawn on, is drawn, but I want no background to be present, just the text.
I would assume I need a combination of TransparentBlt and AlphaBlend.
How would I go on to solve this?
The solution was quite simple. It was to use AC_SRC_ALPHA for the AlphaFormat member of BLENDFUNCTION and in order for that to work, set the alpha values of the HBITMAP, the buffer.
After the buffer (the one inside of NUMBERINFO) is created (in CreateNumber; check question code for reference), one must loop over all the colors and set the alpha value to 255 where needed.
for(int i = s.cx * s.cy; i--; pvBits++)
{
if(*pvBits)
*pvBits |= 0xFF000000; // make non black pixels opaque
}
And setting the flag in WM_PAINT: bfn.AlphaFormat = AC_SRC_ALPHA;

opengl win32 not drawing to screen

I am trying to use glClearBufferfv(GL_COLOR, 0, red) to draw a red screen.
The program displays a white screen and the loading icon on the cursor is continually rotating.
I am using glew. I am also using visual studio and i think i have linked to all the necessary libraries. I employed the whole create a temporary context to use the wglCreateContextAttribsARB extension thing.
I have 2 functions for setting things up. the first one creates the window and sets up the pfd: (the editor is not formatting my code correctly so i will leave out the function names)
int pf;
HDC hDC;
HWND hWnd;
WNDCLASS wc;
PIXELFORMATDESCRIPTOR pfd;
static HINSTANCE hInstance = 0;
if (!hInstance) {
hInstance = GetModuleHandle(NULL);
wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = L"OpenGL";
if (!RegisterClass(&wc)) {
MessageBox(NULL, (LPCWSTR)L"RegisterClass() failed: ", (LPCWSTR)L"Error", MB_OK);
return NULL;
}
}
hWnd = CreateWindow(TEXT("OpenGL"), TEXT("Pie"), WS_OVERLAPPEDWINDOW |
WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
x, y, width, height, NULL, NULL, hInstance, NULL);
if (hWnd == NULL) {
MessageBox(NULL, TEXT("CreateWindow() failed: Cannot create a window."),
TEXT("Error"), MB_OK);
return NULL;
}
hDC = GetDC(hWnd);
/* there is no guarantee that the contents of the stack that become
the pfd are zeroed, therefore _make sure_ to clear these bits. */
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, L"ChoosePixelFormat() failed: "
"Cannot find a suitable pixel format.", L"Error", MB_OK);
return 0;
}
if (SetPixelFormat(hDC, pf, &pfd) == FALSE) {
MessageBox(NULL, L"SetPixelFormat() failed: "
"Cannot set format specified.", L"Error", MB_OK);
return 0;
}
DescribePixelFormat(hDC, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
ReleaseDC(hWnd, hDC);
return hWnd;
The second one creates the context and starts the message loop:
HDC hDC;
HGLRC hRCt, hRC;
HWND hWnd;
MSG msg;
hWnd = CreateOpenGLWindow("minimal", 0, 0, 256, 256, PFD_TYPE_RGBA, 0);
if (hWnd == NULL)
exit(1);
hDC = GetDC(hWnd);
hRCt = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRCt);
glewExperimental = true;
glewInit();
int attribs[] =
{
WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
WGL_CONTEXT_MINOR_VERSION_ARB, 5,
WGL_CONTEXT_FLAGS_ARB, 0,
0
};
hRC = wglCreateContextAttribsARB(hDC, 0, attribs);
wglMakeCurrent(hDC, NULL);
wglDeleteContext(hRCt);
wglMakeCurrent(hDC, hRC);
ShowWindow(hWnd, nCmdShow);
while (GetMessage(&msg, hWnd, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
wglMakeCurrent(NULL, NULL);
ReleaseDC(hWnd, hDC);
wglDeleteContext(hRC);
DestroyWindow(hWnd);
return msg.wParam;
Here is my wndproc:
static PAINTSTRUCT ps;
switch (uMsg) {
case WM_PAINT:
display();
BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
return 0;
case WM_SIZE:
//glViewport(0, 0, LOWORD(lParam), HIWORD(lParam));
PostMessage(hWnd, WM_PAINT, 0, 0);
return 0;
case WM_CHAR:
switch (wParam) {
case 27: /* ESC key */
PostQuitMessage(0);
break;
}
return 0;
case WM_CLOSE:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
and here is my display function:
glClearBufferfv(GL_COLOR, 0, red);
glFlush();
red is a global variable defined as:
GLfloat red[4] = {1, 0, 0, 1};
Any help on why it's not drawing to the screen?
Please put display() between BeginPaint and EndPaint.
Start the painting operation by calling the BeginPaint function.
This function fills in the PAINTSTRUCT structure with information on
the repaint request.
After you are done painting, call the EndPaint function. This function
clears the update region, which signals to Windows that the window has
completed painting itself.
Refer: Painting the Window
Use an example to quickly restore the problem:
HDC hdc = GetDC(hWnd);
case WM_PAINT:
{
PAINTSTRUCT ps;
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 2));
BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
}
Debug:
HDC hdc = GetDC(hWnd);
case WM_PAINT:
{
PAINTSTRUCT ps;
BeginPaint(hWnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 2));
EndPaint(hWnd, &ps);
}
Debug:

Resources