Hi, @RL Chen
Here is an example to passthrough screen specific HWNDs based on MSDN sample.
I tested "NotePad" . HWND hwndNotepad = FindWindow(L"NotePad", NULL);
Create a C++ desktop app. Replace the code below.
Code:
//Ensure that the following definition is in effect before winuser.h is included.
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif
#include <windows.h>
#include <wincodec.h>
#include <magnification.h>
#include <fstream>
#include"resource.h"
#pragma comment(lib, "Magnification.lib")
#pragma comment(lib, "Gdiplus.lib")
//For simplicity, the sample uses a constant magnification factor.
// Global variables and strings.
HINSTANCE hInst;
const TCHAR WindowClassName[] = TEXT("MagnifierWindow");
const TCHAR WindowTitle[] = TEXT("Screen Magnifier Sample");
const UINT timerInterval = 16; // close to the refresh rate @60hz
HWND hwndMag;
HWND hwndHost;
RECT magWindowRect;
RECT hostWindowRect;
// Forward declarations.
LRESULT CALLBACK HostWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
ATOM RegisterHostWindowClass(HINSTANCE hInstance);
BOOL SetupMagnifier(HINSTANCE hinst);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void CALLBACK UpdateMagWindow(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
void GoFullScreen();
BOOL isFullScreen = FALSE;
int CaptureAnImage(HWND hWnd);
BOOL MagImageScaling(HWND hwnd, void* srcdata, MAGIMAGEHEADER srcheader,
void* destdata, MAGIMAGEHEADER destheader,
RECT unclipped, RECT clipped, HRGN dirty)
{
BITMAPINFOHEADER bmif;
BITMAPFILEHEADER bmfh;
bmif.biSize = sizeof(BITMAPINFOHEADER);
bmif.biHeight = srcheader.height;
bmif.biWidth = srcheader.width;
bmif.biSizeImage = bmif.biWidth * bmif.biHeight * 4;
bmif.biPlanes = 1;
bmif.biBitCount = (WORD)(bmif.biSizeImage / bmif.biHeight / bmif.biWidth * 8);
bmif.biCompression = BI_RGB;
LONG offBits = sizeof(BITMAPFILEHEADER) + bmif.biSize;
bmfh.bfType = 0x4d42; // "BM"
bmfh.bfOffBits = offBits;
bmfh.bfSize = offBits + bmif.biSizeImage;
bmfh.bfReserved1 = 0;
bmfh.bfReserved2 = 0;
LPBYTE pData = (BYTE*)new BYTE[bmif.biSizeImage];
memcpy(pData, (LPBYTE)srcdata + srcheader.offset, bmif.biSizeImage);
LONG nLineSize = bmif.biWidth * bmif.biBitCount / 8;
BYTE* pLineData = new BYTE[nLineSize];
LONG nLineStartIndex = 0;
LONG nLineEndIndex = bmif.biHeight - 1;
while (nLineStartIndex < nLineEndIndex)
{
BYTE* pStart = pData + (nLineStartIndex * nLineSize);
BYTE* pEnd = pData + (nLineEndIndex * nLineSize);
memcpy(pLineData, pStart, nLineSize);
memcpy(pStart, pEnd, nLineSize);
memcpy(pEnd, pLineData, nLineSize);
nLineStartIndex++;
nLineEndIndex--;
}
delete[] pLineData;
pLineData = nullptr;
std::ofstream ofs(L"screenshot.bmp", std::fstream::out | std::fstream::binary);
if (ofs.is_open())
{
ofs.write((const char*)&bmfh, sizeof(BITMAPFILEHEADER));
ofs.write((const char*)&bmif, sizeof(BITMAPINFOHEADER));
ofs.write((const char*)pData, bmif.biSizeImage);
ofs.close();
}
delete[] pData;
pData = nullptr;
//MessageBox(hwndHost,L"saved",L"",NULL);
PostQuitMessage(0);
return 1;
}
//
// FUNCTION: WinMain()
//
// PURPOSE: Entry point for the application.
//
int APIENTRY WinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE /*hPrevInstance*/,
_In_ LPSTR /*lpCmdLine*/,
_In_ int nCmdShow)
{
if (FALSE == MagInitialize())
{
return 0;
}
hwndHost = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, HostWndProc);
SetWindowLong(hwndHost, GWL_EXSTYLE, WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_TRANSPARENT);
int xSpan = GetSystemMetrics(SM_CXSCREEN);
int ySpan = GetSystemMetrics(SM_CYSCREEN);
int xBorder = GetSystemMetrics(SM_CXFRAME);
int yCaption = GetSystemMetrics(SM_CYCAPTION);
int yBorder = GetSystemMetrics(SM_CYFRAME);
// Calculate the window origin and span for full-screen mode.
int xOrigin = -xBorder;
int yOrigin = -yBorder - yCaption;
xSpan += 2 * xBorder;
ySpan += 2 * yBorder + yCaption;
SetWindowPos(hwndHost, HWND_TOPMOST, xOrigin, yOrigin, xSpan, ySpan,
SWP_SHOWWINDOW | SWP_NOZORDER | SWP_NOACTIVATE);
if (FALSE == SetupMagnifier(hInstance))
{
return 0;
}
ShowWindow(hwndHost, nCmdShow);
// Create a timer to update the control.
UINT_PTR timerId = SetTimer(hwndHost, 0, timerInterval, UpdateMagWindow);
// Main message loop.
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Shut down.
KillTimer(NULL, timerId);
MagUninitialize();
return (int)msg.wParam;
}
//
// FUNCTION: HostWndProc()
//
// PURPOSE: Window procedure for the window that hosts the magnifier control.
//
LRESULT CALLBACK HostWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_SIZE:
if (hwndMag != NULL)
{
GetClientRect(hWnd, &magWindowRect);
int xSpan = GetSystemMetrics(SM_CXSCREEN);
int ySpan = GetSystemMetrics(SM_CYSCREEN);
// Calculate the size of system elements.
int xBorder = GetSystemMetrics(SM_CXFRAME);
int yCaption = GetSystemMetrics(SM_CYCAPTION);
int yBorder = GetSystemMetrics(SM_CYFRAME);
// Calculate the window origin and span for full-screen mode.
int xOrigin = -xBorder;
int yOrigin = -yBorder - yCaption;
xSpan += 2 * xBorder;
ySpan += 2 * yBorder + yCaption;
// Resize the control to fill the window.
SetWindowPos(hwndMag, NULL,
magWindowRect.left, magWindowRect.top, magWindowRect.right+ yCaption, magWindowRect.bottom + 2 * yBorder + 2 * yCaption, 0);
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
//
// FUNCTION: RegisterHostWindowClass()
//
// PURPOSE: Registers the window class for the window that contains the magnification control.
//
ATOM RegisterHostWindowClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex = {};
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = HostWndProc;
wcex.hInstance = hInstance;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE);
wcex.lpszClassName = WindowClassName;
return RegisterClassEx(&wcex);
}
//
// FUNCTION: SetupMagnifier
//
// PURPOSE: Creates the windows and initializes magnification.
//
BOOL SetupMagnifier(HINSTANCE hinst)
{
// Set bounds of host window according to screen size.
hostWindowRect.top = 0;
hostWindowRect.bottom = GetSystemMetrics(SM_CYSCREEN); // top quarter of screen
hostWindowRect.left = 0;
hostWindowRect.right = GetSystemMetrics(SM_CXSCREEN);
// Create the host window.
RegisterHostWindowClass(hinst);
if (!hwndHost)
{
return FALSE;
}
// Make the window opaque.
SetLayeredWindowAttributes(hwndHost, 0, 255, LWA_ALPHA);
// Create a magnifier control that fills the client area.
GetClientRect(hwndHost, &magWindowRect);
hwndMag = CreateWindow(WC_MAGNIFIER, TEXT("MagnifierWindow"),
WS_CHILD | MS_SHOWMAGNIFIEDCURSOR | WS_VISIBLE,
magWindowRect.left, magWindowRect.top, magWindowRect.right, magWindowRect.bottom, hwndHost, NULL, hInst, NULL);
GoFullScreen();
if (!hwndMag)
{
return FALSE;
}
HWND hwndNotepad = FindWindow(L"NotePad", NULL);
HWND hwndArray[] = { hwndNotepad };
int Size = 1;//size of Array
MagSetWindowFilterList(hwndMag, MW_FILTERMODE_EXCLUDE, Size, hwndArray);
if (!MagSetImageScalingCallback(hwndMag, (MagImageScalingCallback)MagImageScaling))
{
return FALSE;
}
return 1;
}
//
// FUNCTION: UpdateMagWindow()
//
// PURPOSE: Sets the source rectangle and updates the window. Called by a timer.
//
void CALLBACK UpdateMagWindow(HWND /*hwnd*/, UINT /*uMsg*/, UINT_PTR /*idEvent*/, DWORD /*dwTime*/)
{
//GetCursorPos(&mousePoint);
int screenWidth = GetSystemMetrics(SM_CXSCREEN);
int screenHeight = GetSystemMetrics(SM_CYSCREEN);
POINT centerPoint;
centerPoint.x = screenWidth / 2;
centerPoint.y = screenHeight / 2;
int width = (int)((magWindowRect.right - magWindowRect.left));
int height = (int)((magWindowRect.bottom - magWindowRect.top));
RECT sourceRect;
sourceRect.left = centerPoint.x - width / 2;
sourceRect.top = centerPoint.y - height / 2;
// Don't scroll outside desktop area.
if (sourceRect.left < 0)
{
sourceRect.left = 0;
}
if (sourceRect.left > GetSystemMetrics(SM_CXSCREEN) - width)
{
sourceRect.left = GetSystemMetrics(SM_CXSCREEN) - width;
}
sourceRect.right = sourceRect.left + width;
if (sourceRect.top < 0)
{
sourceRect.top = 0;
}
if (sourceRect.top > GetSystemMetrics(SM_CYSCREEN) - height)
{
sourceRect.top = GetSystemMetrics(SM_CYSCREEN) - height;
}
sourceRect.bottom = sourceRect.top + height;
// Set the source rectangle for the magnifier control.
MagSetWindowSource(hwndMag, sourceRect);
// Reclaim topmost status, to prevent unmagnified menus from remaining in view.
SetWindowPos(hwndHost, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
// Force redraw.
InvalidateRect(hwndMag, NULL, TRUE);
}
//
// FUNCTION: GoFullScreen()
//
// PURPOSE: Makes the host window full-screen by placing non-client elements outside the display.
//
void GoFullScreen()
{
isFullScreen = TRUE;
// The window must be styled as layered for proper rendering.
// It is styled as transparent so that it does not capture mouse clicks.
SetWindowLong(hwndHost, GWL_EXSTYLE, WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_TRANSPARENT);
// Give the window a system menu so it can be closed on the taskbar.
SetWindowLong(hwndHost, GWL_STYLE, WS_CAPTION | WS_SYSMENU);
// Calculate the span of the display area.
HDC hDC = GetDC(NULL);
int xSpan = GetSystemMetrics(SM_CXSCREEN);
int ySpan = GetSystemMetrics(SM_CYSCREEN);
ReleaseDC(NULL, hDC);
// Calculate the size of system elements.
int xBorder = GetSystemMetrics(SM_CXFRAME);
int yCaption = GetSystemMetrics(SM_CYCAPTION);
int yBorder = GetSystemMetrics(SM_CYFRAME);
// Calculate the window origin and span for full-screen mode.
int xOrigin = -xBorder;
int yOrigin = -yBorder - yCaption;
xSpan += 2 * xBorder;
ySpan += 2 * yBorder + yCaption;
SetWindowPos(hwndHost, HWND_TOPMOST, xOrigin, yOrigin, xSpan, ySpan,
SWP_NOZORDER | SWP_NOACTIVATE);
}
Best regards,
Minxin Yu
If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.