Resizing bitmap for CreatePatternBrush when printing - winapi

I am trying to print a brush pattern like I see on the screen but I get different results depending on the printer DC. I use Microsoft PDF or a printer. Both are printing using 600 DPI. I'm trying to get the same pattern when I'm printing by resizing the bitmap that is being used by CreatePatternBrush. This seems to work fine for Microsoft PDF but not for the printer. The pattern using the printer is way too large. Any clue why?
OnBnClickedButtonprint is where I'm trying to print where ScaleBitmap is done on the pattern bitmap. Here is the code:
#include "stdafx.h"
#include "Printing.h"
#include "PrintingDlg.h"
#include "afxdialogex.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
RECT rcSmall = { 25, 25, 75, 75 };
RECT rcBig = { 55, 55, 255, 255 };
RECT rcWholeArea = { 0, 0, 300, 300 };
COLORREF crRed = RGB(255, 0, 0);
COLORREF crGreen = RGB(0, 255, 0);
COLORREF crBlue = RGB(0, 0, 255);
COLORREF crWhite = RGB(255, 255, 255);
COLORREF crBlack = RGB(0, 0, 0);
CPrintingDlg::CPrintingDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(IDD_PRINTING_DIALOG, pParent)
{
WORD HatchBits[8] = { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe };
m_hBitmap = ::CreateBitmap(8, 8, 1, 1, HatchBits);
}
void CPrintingDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CPrintingDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTONPRINT, &CPrintingDlg::OnBnClickedButtonprint)
END_MESSAGE_MAP()
// CPrintingDlg message handlers
BOOL CPrintingDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
return TRUE; // return TRUE unless you set the focus to a control
}
HBITMAP CPrintingDlg::ScaleBitmap(HDC hdc, HBITMAP hBitmapSrc)
{
double gDPIScaleX = GetDeviceCaps(hdc, LOGPIXELSX) / 96.0f;
double gDPIScaleY = GetDeviceCaps(hdc, LOGPIXELSY) / 96.0f;
if (gDPIScaleX == 1.0 && gDPIScaleY == 1.0)
return hBitmapSrc;
// Get logical coordinates
BITMAP bm;
::GetObject(hBitmapSrc, sizeof(bm), &bm);
int iWidth = (int)(bm.bmWidth * gDPIScaleX);
int iHeight = (int)(bm.bmHeight * gDPIScaleY);
// Select the source DC
HDC hdcSrc = ::CreateCompatibleDC(hdc);
HBITMAP hBitmapOldSrc = (HBITMAP)::SelectObject(hdcSrc, hBitmapSrc);
// Create the bitmap and select the destination DC
HDC hdcDst = ::CreateCompatibleDC(hdc);
HBITMAP hBitmapDst = ::CreateCompatibleBitmap(hdcDst, iWidth, iHeight);
HBITMAP hBitmapOldDst = (HBITMAP)::SelectObject(hdcDst, hBitmapDst);
// Resize
::StretchBlt(hdcDst, 0, 0, iWidth, iHeight, hdcSrc, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
// Reselect the old bitmaps
::SelectObject(hdcSrc, hBitmapOldSrc);
::SelectObject(hdcDst, hBitmapOldDst);
// Delete the resources
DeleteDC(hdcSrc);
DeleteDC(hdcDst);
return hBitmapDst;
}
RECT CPrintingDlg::ScaleRect(HDC hdc, RECT rcOriginal)
{
double gDPIScaleX = GetDeviceCaps(hdc, LOGPIXELSX) / 96.0f;
double gDPIScaleY = GetDeviceCaps(hdc, LOGPIXELSY) / 96.0f;
if (gDPIScaleX == 1.0 && gDPIScaleY == 1.0)
return rcOriginal;
RECT rcScaled;
rcScaled.left = (long)(rcOriginal.left * gDPIScaleX);
rcScaled.right = (long)(rcOriginal.right * gDPIScaleX);
rcScaled.top = (long)(rcOriginal.top * gDPIScaleY);
rcScaled.bottom = (long)(rcOriginal.bottom * gDPIScaleY);
return rcScaled;
}
void CPrintingDlg::DrawRectangle(HDC hdc, RECT rect, COLORREF cr)
{
HPEN hPen = ::CreatePen(PS_SOLID, 1, cr);
::SelectObject(hdc, hPen);
HBRUSH hBrush = ::CreateSolidBrush(cr);
::SelectObject(hdc, hBrush);
::Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);
}
void CPrintingDlg::DrawPatternRectangle(HDC hdc, HBITMAP hBitmap, RECT rect, COLORREF cr)
{
int oldROP2 = 0;
HPEN hPen = ::CreatePen(PS_SOLID, 1, crBlack);
::SelectObject(hdc, hPen);
HBRUSH hPatternBrush = ::CreatePatternBrush(hBitmap);
::SelectObject(hdc, hPatternBrush);
::SetTextColor(hdc, crBlack);
if (::GetROP2(hdc) == R2_COPYPEN)
{
::SetBkColor(hdc, crWhite);
oldROP2 = ::SetROP2(hdc, R2_MASKNOTPEN);
::Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);
::SetBkColor(hdc, cr);
::SetROP2(hdc, R2_MERGEPEN);
::Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);
::SetROP2(hdc, oldROP2);
}
else
{
::SetBkColor(hdc, cr);
::Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);
}
}
void CPrintingDlg::OnPaint()
{
CPaintDC hdc(this);
DrawRectangle(hdc, rcWholeArea, crWhite);
DrawRectangle(hdc, rcSmall, crGreen);
DrawPatternRectangle(hdc, m_hBitmap, rcBig, crRed);
}
void CPrintingDlg::OnBnClickedButtonprint()
{
CPrintDialog dlgPrint(FALSE, PD_NOSELECTION);
dlgPrint.GetDefaults();
dlgPrint.m_pd.Flags &= ~PD_RETURNDEFAULT;
DEVMODE* dm = (DEVMODE*)GlobalLock(dlgPrint.m_pd.hDevMode);
dm->dmFields |= DM_ORIENTATION;
dm->dmOrientation = DMORIENT_LANDSCAPE;
GlobalUnlock(dlgPrint.m_pd.hDevMode);
dlgPrint.DoModal();
HDC hdc = dlgPrint.GetPrinterDC();
DOCINFO docInfo;
ZeroMemory(&docInfo, sizeof(docInfo));
docInfo.cbSize = sizeof(docInfo);
docInfo.lpszDocName = _T("PrintTest");
StartDoc(hdc, &docInfo);
StartPage(hdc);
DrawRectangle(hdc, ScaleRect(hdc, rcWholeArea), crWhite);
DrawRectangle(hdc, ScaleRect(hdc, rcSmall), crGreen);
DrawPatternRectangle(hdc, ScaleBitmap(hdc, m_hBitmap), ScaleRect(hdc, rcBig), crRed);
EndPage(hdc);
EndDoc(hdc);
DeleteDC(hdc);
}
Here is what I'm trying to print:

Related

C++ Transparent image using windows.h / WinAPI

I'm trying to make a custom title bar/border and I want it to be half transparent. When I load the image it works fine, but as soon, as I make even just 1 pixel from 255 opacity to 254, it just shows a white image.
Help would really be appreciated!
I use the windows.h library.
I use a resource ( .rc ) file to get the location of the images.
Don't think about where im doing things right, it's just for testing. I know it's not very efficient.
The Code!
( or at least the most of it / the important )
#include "../resource/resource.h"
#include "../header/Window.h"
#pragma warning(disable : 4244)
/////////////////////////
// Window
//
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
HWND m_hWnd;
POINT wndSize = { 900, 900 };
Window::Window() : m_hInstance(GetModuleHandle(nullptr))
{
const wchar_t * className = L"Main Window";
WNDCLASS wc = {};
wc.lpszClassName = className;
wc.hInstance = m_hInstance;
wc.hIcon = LoadIcon(m_hInstance, MAKEINTRESOURCE(IDI_ICON));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpfnWndProc = WindowProc;
wc.hbrBackground = CreatePatternBrush(LoadBitmap(m_hInstance, MAKEINTRESOURCE(IDB_BG)));
RegisterClass(&wc);
DWORD style = NULL;
RECT rect;
rect.left = GetSystemMetrics(SM_CXSCREEN) * .5 - (wndSize.x * .5);
rect.top = GetSystemMetrics(SM_CYSCREEN) * .5 - (wndSize.y * .5);
rect.right = rect.left + wndSize.x;
rect.bottom = rect.top + wndSize.y;
AdjustWindowRect(&rect, style, false);
m_hWnd = CreateWindowEx(
0,
className,
L"Chess",
style,
rect.left,
rect.top,
rect.right - rect.left,
rect.bottom - rect.top,
NULL,
NULL,
m_hInstance,
NULL
);
SetWindowLongPtr(m_hWnd, GWL_STYLE, NULL); // Remove the default borders
ShowWindow(m_hWnd, SW_SHOW);
}
Window::~Window()
{
const wchar_t * className = L"Main Window";
UnregisterClass(className, m_hInstance);
}
bool Window::ProcessMessage()
{
MSG msg = {};
RECT rectBorder;
HBRUSH colorBorder = CreatePatternBrush(LoadBitmap(m_hInstance, MAKEINTRESOURCE(IDB_TOP)));
//BitBlt(GetWindowDC(m_hWnd), 0, 0, 900, 30, GetWindowDC(m_hWnd), 0, 0, SRCINVERT);
//BitBlt(GetWindowDC(m_hWnd), 0, 0, 900, 30, GetWindowDC(m_hWnd), 0, 0, SRCAND);
//BitBlt(GetWindowDC(m_hWnd), 0, 0, 900, 30, GetWindowDC(m_hWnd), 0, 0, SRCINVERT);
while(PeekMessage(&msg, nullptr, 0u, 0u, PM_REMOVE))
{
switch(msg.message)
{
case WM_MOUSEMOVE: // On mouse motion
Window::updateWndEvents();
break;
case WM_PAINT: // On draw request
rectBorder = { 0, 0, wndSize.x, 30 };
FillRect(GetWindowDC(m_hWnd), &rectBorder, colorBorder); // Draw the top border
break;
case WM_QUIT: // On quit
return false;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return true;
}
/////////////////////////
// Window Functions
//
void Window::resizeWindow()
{
}
void Window::moveWindow()
{
}
void Window::updateWndEvents()
{
}
The alpha channel of a PNG image cannot be loaded using LoadBitmap.
It is recommended to use LockBits with PixelFormat32bppARGB in GDI+.

Make a win32 window transparent to messages (click, touch, keyboard)

I created a semi transparent window using the source code from this discussion (posted by wilkie):
How to make an OpenGL rendering context with transparent background?
It works, but I would like my window not to pick up mouse, touch and keyboard click messages.
But above all, I would like these messages (click, touch, keyboard) to be received by the application located below my transparent window.
Example:
My transparent window (TOP_MOST) is located on top of NotePad ++. If I click on my transparent window, I want this click to be received by NotePad++ and not by my transparent window.
I did not find valid answers on the Internet.
I see two possibilities:
_ Make my window transparent to all messages
_ Or my transparent window must receive the messages, not react and redirect them by sending them to the window located below.
In both cases, I don't know how to do it :)
Is it possible ?
Regards,
Edit with code:
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <windowsx.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <dwmapi.h>
#pragma comment (lib, "opengl32.lib")
#pragma comment (lib, "glu32.lib")
#pragma comment (lib, "dwmapi.lib")
#include <assert.h>
#include <tchar.h>
#ifdef assert
#define verify(expr) if(!expr) assert(0)
#else verify(expr) expr
#endif
const TCHAR szAppName[] = _T("TransparentGL");
const TCHAR wcWndName[] = _T("TransparentGL");
HDC hDC;
HGLRC m_hrc;
int w = 240;
int h = 240;
BOOL initSC() {
glEnable(GL_ALPHA_TEST);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0, 0, 0, 0);
return 0;
}
void resizeSC(int width, int height) {
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
BOOL renderSC() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glColor3f(0, 1, 1);
glBegin(GL_TRIANGLES); // Drawing Using Triangles
glColor3f(1.0f, 0.0f, 0.0f); // Set The Color To Red
glVertex3f(0.0f, 1.0f, 0.0f); // Top
glColor3f(0.0f, 1.0f, 0.0f); // Set The Color To Green
glVertex3f(-1.0f, -1.0f, 0.0f); // Bottom Left
glColor3f(0.0f, 0.0f, 1.0f); // Set The Color To Blue
glVertex3f(1.0f, -1.0f, 0.0f); // Bottom Right
glEnd();
glPopMatrix();
glFlush();
return 0;
}
BOOL CreateHGLRC(HWND hWnd) {
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR),
1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_SUPPORT_COMPOSITION | // Format Must Support Composition
PFD_DOUBLEBUFFER, // Must Support Double Buffering
PFD_TYPE_RGBA, // Request An RGBA Format
32, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
8, // An Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
24, // 16Bit Z-Buffer (Depth Buffer)
8, // Some Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Reserved
0, 0, 0 // Layer Masks Ignored
};
HDC hdc = GetDC(hWnd);
int PixelFormat = ChoosePixelFormat(hdc, &pfd);
if (PixelFormat == 0) {
assert(0);
return FALSE;
}
BOOL bResult = SetPixelFormat(hdc, PixelFormat, &pfd);
if (bResult == FALSE) {
assert(0);
return FALSE;
}
m_hrc = wglCreateContext(hdc);
if (!m_hrc) {
assert(0);
return FALSE;
}
ReleaseDC(hWnd, hdc);
return TRUE;
}
LRESULT CALLBACK WindowFunc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CREATE:
break;
case WM_DESTROY:
if (m_hrc) {
wglMakeCurrent(NULL, NULL);
wglDeleteContext(m_hrc);
}
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR str, int nWinMode) {
WNDCLASSEX wc;
memset(&wc, 0, sizeof(wc));
wc.cbSize = sizeof(WNDCLASSEX);
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WindowFunc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hThisInst;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)CreateSolidBrush(0x00000000);
wc.lpszClassName = szAppName;
if (!RegisterClassEx(&wc)) {
MessageBox(NULL, _T("RegisterClassEx - failed"), _T("Error"), MB_OK | MB_ICONERROR);
return FALSE;
}
HWND hWnd = CreateWindowEx(WS_EX_APPWINDOW | WS_EX_TOPMOST | WS_EX_TRANSPARENT, szAppName, wcWndName,
WS_VISIBLE | WS_POPUP, 200, 150, w, h,
NULL, NULL, hThisInst, NULL);
if (!hWnd) {
MessageBox(NULL, _T("CreateWindowEx - failed"), _T("Error"), MB_OK | MB_ICONERROR);
return FALSE;
}
DWM_BLURBEHIND bb = { 0 };
HRGN hRgn = CreateRectRgn(0, 0, -1, -1);
bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
bb.hRgnBlur = hRgn;
bb.fEnable = TRUE;
DwmEnableBlurBehindWindow(hWnd, &bb);
CreateHGLRC(hWnd);
HDC hdc = GetDC(hWnd);
wglMakeCurrent(hdc, m_hrc);
initSC();
resizeSC(w, h);
ReleaseDC(hWnd, hdc);
MSG msg;
while (1) {
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else {
HDC hdc = GetDC(hWnd);
wglMakeCurrent(hdc, m_hrc);
renderSC();
SwapBuffers(hdc);
ReleaseDC(hWnd, hdc);
}
}
return (FALSE);
}
You can add the WS_EX_LAYERED style when creating the form, and set the opacity of the window through the SetLayeredWindowAttributes function.
HWND hWnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_APPWINDOW | WS_EX_TOPMOST | WS_EX_TRANSPARENT, szAppName, wcWndName,
WS_VISIBLE | WS_POPUP, 200, 150, w, h,
NULL, NULL, hThisInst, NULL);
if (!hWnd) {
MessageBox(NULL, _T("CreateWindowEx - failed"), _T("Error"), MB_OK | MB_ICONERROR);
return FALSE;
}
SetLayeredWindowAttributes(hWnd, 0, 255, LWA_ALPHA);
Then it works for me:
Thanks to Zhu Song - MSFT and David Heffernan, this is the full source code of the modified sample originaly posted in this post:
How to make an OpenGL rendering context with transparent background?
It display an OpenGL Triangle in transparente Window and support Click-Through:
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <windowsx.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <dwmapi.h>
#pragma comment (lib, "opengl32.lib")
#pragma comment (lib, "glu32.lib")
#pragma comment (lib, "dwmapi.lib")
#include <assert.h>
#include <tchar.h>
#ifdef assert
#define verify(expr) if(!expr) assert(0)
#else verify(expr) expr
#endif
const TCHAR szAppName[] = _T("TransparentGL");
const TCHAR wcWndName[] = _T("TransparentGL");
HDC hDC;
HGLRC m_hrc;
int w = 240;
int h = 240;
BOOL initSC() {
glEnable(GL_ALPHA_TEST);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0, 0, 0, 0);
return 0;
}
void resizeSC(int width, int height) {
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
BOOL renderSC() {
static float angle = 0.0f;
angle = (angle < 360.0f ) ? angle + 0.01f : 0.0f;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glRotatef(angle, 0.0f, 0.0f, 1.0f);
glColor3f(0, 1, 1);
glBegin(GL_TRIANGLES); // Drawing Using Triangles
glColor4f(1.0f, 0.0f, 0.0f,0.5f); // Set The Color To Red
glVertex3f(0.0f, 1.0f, 0.0f); // Top
glColor4f(0.0f, 1.0f, 0.0f, 0.5f); // Set The Color To Green
glVertex3f(-1.0f, -1.0f, 0.0f); // Bottom Left
glColor4f(0.0f, 0.0f, 1.0f, 0.5f); // Set The Color To Blue
glVertex3f(1.0f, -1.0f, 0.0f); // Bottom Right
glEnd();
glPopMatrix();
glFlush();
return 0;
}
BOOL CreateHGLRC(HWND hWnd) {
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR),
1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_SUPPORT_COMPOSITION | // Format Must Support Composition
PFD_DOUBLEBUFFER, // Must Support Double Buffering
PFD_TYPE_RGBA, // Request An RGBA Format
32, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
8, // An Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
24, // 16Bit Z-Buffer (Depth Buffer)
8, // Some Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Reserved
0, 0, 0 // Layer Masks Ignored
};
HDC hdc = GetDC(hWnd);
int PixelFormat = ChoosePixelFormat(hdc, &pfd);
if (PixelFormat == 0) {
assert(0);
return FALSE;
}
BOOL bResult = SetPixelFormat(hdc, PixelFormat, &pfd);
if (bResult == FALSE) {
assert(0);
return FALSE;
}
m_hrc = wglCreateContext(hdc);
if (!m_hrc) {
assert(0);
return FALSE;
}
ReleaseDC(hWnd, hdc);
return TRUE;
}
LRESULT CALLBACK WindowFunc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
PAINTSTRUCT ps;
switch (msg) {
case WM_CREATE:
break;
case WM_DESTROY:
if (m_hrc) {
wglMakeCurrent(NULL, NULL);
wglDeleteContext(m_hrc);
}
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR str, int nWinMode) {
WNDCLASSEX wc;
memset(&wc, 0, sizeof(wc));
wc.cbSize = sizeof(WNDCLASSEX);
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WindowFunc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hThisInst;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)CreateSolidBrush(0x00000000);
wc.lpszClassName = szAppName;
if (!RegisterClassEx(&wc)) {
MessageBox(NULL, _T("RegisterClassEx - failed"), _T("Error"), MB_OK | MB_ICONERROR);
return FALSE;
}
HWND hWnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_APPWINDOW | WS_EX_TOPMOST | WS_EX_TRANSPARENT, szAppName, wcWndName,
WS_VISIBLE | WS_POPUP, 200, 150, w, h,
NULL, NULL, hThisInst, NULL);
if (!hWnd) {
MessageBox(NULL, _T("CreateWindowEx - failed"), _T("Error"), MB_OK | MB_ICONERROR);
return FALSE;
}
SetLayeredWindowAttributes(hWnd, 0, 255, LWA_ALPHA);
DWM_BLURBEHIND bb = { 0 };
HRGN hRgn = CreateRectRgn(0, 0, -1, -1);
bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
bb.hRgnBlur = hRgn;
bb.fEnable = TRUE;
DwmEnableBlurBehindWindow(hWnd, &bb);
CreateHGLRC(hWnd);
HDC hdc = GetDC(hWnd);
wglMakeCurrent(hdc, m_hrc);
initSC();
resizeSC(w, h);
ReleaseDC(hWnd, hdc);
MSG msg;
while (1) {
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else {
HDC hdc = GetDC(hWnd);
wglMakeCurrent(hdc, m_hrc);
renderSC();
SwapBuffers(hdc);
ReleaseDC(hWnd, hdc);
}
}
return (FALSE);
}
If it can help other peoples, if you want to do the same thing with QT:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
_glWidget = new MyOpenGLWidget(this); // derived from: public QOpenGLWidget, protected QOpenGLFunctions_3_3_Core
setAttribute(Qt::WA_InputMethodTransparent);
setAttribute(Qt::WA_TranslucentBackground, true);
setAttribute(Qt::WA_TransparentForMouseEvents);
SetForegroundWindow((HWND)winId());
setWindowFlags(Qt::Window | Qt::FramelessWindowHint |Qt::WindowStaysOnTopHint);
ui->verticalLayout->addWidget(_glWidget);
}

how to capture window in windows 10 with c++

I tried use gdi to capture certain window, it's ok for most window.
But to some window like "visual studio code", it doesn't work.
DX can't support capturing certain window.
How should I do? THANKS
::EnumWindows(EnumWindowsProc, NULL);
if (hCapWnd == NULL)
{
return FALSE;
}
SwitchToThisWindow(hCapWnd, true);
Sleep(1000);
//HWND hDesktopWnd = GetDesktopWindow();
HDC hDesktopDC = GetWindowDC(hCapWnd);
HDC hCaptureDC = CreateCompatibleDC(hDesktopDC);
SetStretchBltMode(hCaptureDC, COLORONCOLOR);
RECT rc;
::GetWindowRect(hCapWnd, &rc);
int width = rc.right - rc.left;
int height = rc.bottom - rc.top;
HBITMAP hCaptureBitmap = CreateCompatibleBitmap(hDesktopDC, width, height);
SelectObject(hCaptureDC, hCaptureBitmap);
BOOL bRet = BitBlt(hCaptureDC, 0, 0, width, height, hDesktopDC, 0, 0, SRCCOPY);
Init(width, height);
int nRet = GetDIBits(hCaptureDC, hCaptureBitmap, 0, height, buf, (BITMAPINFO*)&m_bitmapInfo, DIB_RGB_COLORS);
static int n = 0;
//if (n++ % 10 == 0)
{
// std::string name = ustd::format_string("%s\\%d.bmp", ustd::get_program_path().c_str(), n);
SaveBitmapToFile(hCaptureBitmap);
}
ReleaseDC(hCapWnd, hDesktopDC);
DeleteDC(hCaptureDC);
DeleteObject(hCaptureBitmap);

How do i Use Fillrect or DrawText on 32bit HBITMAP in C++

i'm sorry for what i did. i edited.
i'd like to use Fillrect on 32bit HBITMAP which is Created with CreateDIBSection
but i can't make rect visible in color that i want to.
(i Drawed a fillrect with CreateSolidBrush blue(RGB(0, 0, 255)) on 32bit HBITMAP(hdcbmp), but it doesn't appear blue.)
here is source code
is there anyway to show rect color that i want to?
sorry for my poor english.
void DrawAlphaBitmap(HWND hWnd, ULONG uWidth, ULONG uHeight)
{
BLENDFUNCTION bf;
HBITMAP hbitmap;
HBITMAP hOldBitmap;
BITMAPINFO bmi;
PVOID pvBits;
HDC hdcwnd = GetDC(hWnd);
HDC hdcbmp = CreateCompatibleDC(hdcwnd);
ZeroMemory(&bmi, sizeof(BITMAPINFO));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = uWidth;
bmi.bmiHeader.biHeight = uHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = bmi.bmiHeader.biWidth * bmi.bmiHeader.biHeight * 4;
hbitmap = CreateDIBSection(hdcbmp, &bmi, DIB_RGB_COLORS, &pvBits, NULL, 0x0);
hOldBitmap = (HBITMAP)SelectObject(hdcbmp, hbitmap);
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 0xff;
bf.AlphaFormat = AC_SRC_ALPHA;
RECT rc2 = { 100, 100, 200, 200 };
FillRect(hdcbmp, &rc2, CreateSolidBrush(RGB(0, 0, 255)));
AlphaBlend(hdcwnd, 0, 0, uWidth, uHeight, hdcbmp, 0, 0, uWidth, uHeight, bf);
SelectObject(hdcbmp, hOldBitmap);
DeleteObject(hbitmap);
DeleteDC(hdcbmp);
ReleaseDC(hWnd, hdcwnd);
}
From documentation for BLENDFUNCTION:
AlphaFormat:
This flag is set when the bitmap has an Alpha channel (that is, per-pixel alpha).
In this case, alpha channel is not set. CreateDIBSection initializes the alpha values to zero. When AC_SRC_ALPHA is set, AlphaBlend ignores pixels whose alpha value is zero. Modify your code as follows:
//bf.AlphaFormat = AC_SRC_ALPHA; <- remove
bf.AlphaFormat = 0; //replace with 0
Side note, you have resource leak in creation of HBRUSH handle. Change the code to
HBRUSH hbrush = CreateSolidBrush(RGB(0, 0, 255));
RECT rc2 = { 0, 0, w, h };
FillRect(memdc, &rc2, hbrush);
DeleteObject(hbrush);
Ideally, your function prototype should be void DrawAlphaBitmap(HDC hdc, ULONG uWidth, ULONG uHeight); so that HDC can be passed directly, for example from BeginPaint/EndPaint in WM_PAINT message.

My code which uses UpdateLayeredWindow doesn't work

I attampted to draw a irregular window with the UpdateLayeredWindow(), in msvc2008, xp sp3.
Here is part of my code:
//Add something(CreateWindowEx()):
hwndCyauWnd = CreateWindowEx(
/*WS_EX_TOOLWINDOW |*/ WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_LAYERED,
lpwsCyauClassName,
lpwsCyauWndName,
WS_CLIPSIBLINGS | WS_POPUP,
GetSystemMetrics(SM_CXSCREEN)-320,
GetSystemMetrics(SM_CYSCREEN)-232,
320, 200,
NULL,
NULL,
hInstance,
NULL);
//Skip Lines
HDC hdcCyauWnd = GetDC(hwndCyauWnd);
HDC hdcBuffer = CreateCompatibleDC(hdcCyauWnd);
//HBITMAP hbmCyau = CreateCompatibleBitmap(hdcBuffer,120, 93);
//SelectObject(hdcBuffer, hbmCyau);
POINT ptZero = {0, 0};
POINT ptDrawPos = {0, 0};
RECT rctCyauWnd;
GetWindowRect(hwndCyauWnd, &rctCyauWnd);
SIZE szCyauWnd={rctCyauWnd.right - rctCyauWnd.left, rctCyauWnd.bottom - rctCyauWnd.top};
BLENDFUNCTION blendPixelFunction = { AC_SRC_OVER, 0, 100, AC_SRC_ALPHA};
Graphics gphCyauWnd(hdcBuffer);
Image imgCyau(L"surface0000.png");
gphCyauWnd.DrawImage(&imgCyau, 0, 0, 125, 93);
UpdateLayeredWindow(hwndCyauWnd,
hdcCyauWnd, &ptZero,
&szCyauWnd,
hdcBuffer, &ptZero,
0, //RGB(255, 255, 255),
&blendPixelFunction,
ULW_ALPHA);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
I have tried several method to use this function, but all failed, NOTHING APPEAR on the screen.
Could anybody tell me what happens and how to slove it?
Add:
Whole source file have been upload to my skydrive, anyone can edit, much appreciation! (I have become a poor underdog now...)
You mixed up GDI and GDI+, which is not a good idea. Here is a working example:
hWnd = CreateWindowEx(WS_EX_LAYERED, szWindowClass, szTitle, 0,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
// Load PNG
CImage img;
img.Load("BACKGR.png");
// Get image sizes
int nWidth = img.GetWidth();
int nHeight = img.GetHeight();
// Create memory DC
HDC hdcScreen = GetDC(NULL);
HDC hDC = CreateCompatibleDC(hdcScreen);
// Create memory bitmap
HBITMAP hBmp = CreateCompatibleBitmap(hdcScreen, nWidth, nHeight);
HBITMAP hBmpOld = (HBITMAP)SelectObject(hDC, hBmp);
// Draw image to memory bitmap (currently selected in memory DC)
img.Draw(hDC, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight);
// Call UpdateLayeredWindow
BLENDFUNCTION blend = {0};
blend.BlendOp = AC_SRC_OVER;
blend.SourceConstantAlpha = 128;// half transparent
blend.AlphaFormat = AC_SRC_ALPHA;
POINT ptLocation = {0, 0};
SIZE szWnd = {nWidth, nHeight};
POINT ptSrc = {0, 0};
UpdateLayeredWindow(hWnd, hdcScreen, &ptLocation, &szWnd, hDC, &ptSrc, 0, &blend, ULW_ALPHA);
ShowWindow(hWnd, SW_SHOW);
SelectObject(hDC, hBmpOld);
DeleteObject(hBmp);
DeleteDC(hDC);
ReleaseDC(NULL, hdcScreen);
If you want GDI+ to draw to an image with an alpha channel, you have to draw to a Bitmap, not an HDC, and you have to specify that the Bitmap's format has alpha. To do that with an HBITMAP, you have to also point GDI+ to the bitmap bits.
Something like this:
BITMAPINFOHEADER bih;
HBITMAP hbmp;
HDC hdc;
void *bits;
bih.biSize = sizeof(bih);
bih.biWidth = width;
bih.biHeight = -height;
bih.biPlanes = 1;
bih.biBitCount = 32;
bih.biCompression = BI_RGB;
bih.biSizeImage = 0;
bih.biXPelsPerMeter = 0;
bih.biYPelsPerMeter = 0;
bih.biClrUsed = 0;
bih.biClrImportant = 0;
hdc = CreateCompatibleDC(NULL);
hbmp = CreateDIBSection(hdc, (BITMAPINFO*)&bih, DIB_RGB_COLORS, &bits, NULL, 0);
Bitmap bitmap(width, height, 0, PixelFormat32bppPARGB, bits);
Graphics graphics(bitmap);
graphics->DrawWhatever(...);
graphics->Flush();
SelectObject(hdc, hbitmap);
UpdateLayeredWindow(hwnd, hdc, ...

Resources