文章目录
- 完整代码
- API简介
- 调试代码
- 后记
- reference
完整代码
server.cpp
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <windows.h>
#include <stdio.h>
#include <vector>
#pragma comment(lib, "ws2_32.lib")
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void RenderBitmap(HDC hdc, BYTE* bBits, int width, int height, int windowWidth, int windowHeight);
class xy {
public:
int x;
int y;
};
int main(void)
{
// Initialize WinSock
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(8888); // Port number
inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr.s_addr);
bind(serverSocket, (sockaddr*)&serverAddr, sizeof(serverAddr));
listen(serverSocket, 5);
// Wait for client connection
SOCKET clientSocket = accept(serverSocket, NULL, NULL);
xy data;
recv(clientSocket, (char*)&data, sizeof(data), 0);
// Register window class
WNDCLASS wc = { 0 };
wc.lpfnWndProc = WndProc;
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = L"ScreenCaptureReceiverWindowClass";
RegisterClass(&wc);
// Set up the bitmap for rendering
BITMAPINFO bInfo;
HBITMAP hBitmap;
BYTE* bBits = nullptr;
int screenWidth = data.x; // Set screen width
int screenHeight = data.y; // Set screen height
int windowWidth = 800;
int windowHeight = 600;
float screenAspect = (float)screenWidth / screenHeight;
float windowAspect = (float)windowWidth / windowHeight;
// Adjust window size to maintain the screen aspect ratio
if (screenAspect > windowAspect)
{
windowHeight = (INT)(windowWidth / screenAspect);
}
else
{
windowWidth = (INT)(windowHeight * screenAspect);
}
RECT rect = { 0, 0, windowWidth, windowHeight };
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
ZeroMemory(&bInfo, sizeof(BITMAPINFO));
bInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bInfo.bmiHeader.biBitCount = 24;
bInfo.bmiHeader.biCompression = BI_RGB;
bInfo.bmiHeader.biPlanes = 1;
bInfo.bmiHeader.biWidth = screenWidth;
bInfo.bmiHeader.biHeight = -screenHeight; // Top-down
HWND hwnd = CreateWindowEx(0, wc.lpszClassName, L"Screen Receiver", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, wc.hInstance, NULL);
ShowWindow(hwnd, SW_SHOW);
HDC hdc = GetDC(hwnd);
hBitmap = CreateDIBSection(hdc, &bInfo, DIB_RGB_COLORS, (VOID**)&bBits, NULL, 0);
// Main message loop
MSG msg = { 0 };
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
// Receive image data from the client
int len = screenWidth * screenHeight * 3;
recv(clientSocket, (char*)bBits, len, 0);
// Render the received bitmap
RenderBitmap(hdc, bBits, screenWidth, screenHeight, windowWidth, windowHeight);
Sleep(200); // Adjust the refresh rate
}
}
// Clean up
DeleteObject(hBitmap);
ReleaseDC(hwnd, hdc);
closesocket(clientSocket);
closesocket(serverSocket);
WSACleanup();
return 0;
}
void RenderBitmap(HDC hdc, BYTE* bBits, int width, int height, int windowWidth, int windowHeight)
{
BITMAPINFO bInfo;
ZeroMemory(&bInfo, sizeof(BITMAPINFO));
bInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bInfo.bmiHeader.biBitCount = 24;
bInfo.bmiHeader.biCompression = BI_RGB;
bInfo.bmiHeader.biPlanes = 1;
bInfo.bmiHeader.biWidth = width;
bInfo.bmiHeader.biHeight = -height;
SetStretchBltMode(hdc, HALFTONE);
StretchDIBits(hdc, 0, 0, windowWidth, windowHeight, 0, 0, width, height, bBits, &bInfo, DIB_RGB_COLORS, SRCCOPY);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
client.cpp
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <windows.h>
#include <vector>
#include<iostream>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
std::vector<int> getxy();
class xyz {
public:
int x;
int y;
};
int main(void)
{
// Initialize WinSock
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(8888); // Port number
inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr.s_addr);// Replace with the server's IP address
connect(clientSocket, (sockaddr*)&serverAddr, sizeof(serverAddr));
// Get screen dimensions
vector<int> xy = getxy();
int screenWidth = xy[0];
int screenHeight = xy[1];
xyz data;
data.x = screenWidth;
data.y = screenHeight;
send(clientSocket, (char*)&data, sizeof(data), 0);
// Set up the screen capture
BITMAPINFO bInfo;
HDC hDC, hMemDC;
HBITMAP hBitmap;
BYTE* bBits = NULL;
hDC = GetDC(NULL);
hMemDC = CreateCompatibleDC(hDC);
ZeroMemory(&bInfo, sizeof(BITMAPINFO));
bInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bInfo.bmiHeader.biBitCount = 24;
bInfo.bmiHeader.biCompression = BI_RGB;
bInfo.bmiHeader.biPlanes = 1;
bInfo.bmiHeader.biWidth = screenWidth;
bInfo.bmiHeader.biHeight = -screenHeight;
hBitmap = CreateDIBSection(hDC, &bInfo, DIB_RGB_COLORS, (VOID**)&bBits, NULL, 0);
SelectObject(hMemDC, hBitmap);
int len = screenWidth * screenHeight * 3;
// Main loop to capture and send screen data
while (true)
{
BitBlt(hMemDC, 0, 0, screenWidth, screenHeight, hDC, 0, 0, SRCCOPY);
send(clientSocket, (char*)bBits, len, 0);
Sleep(20); // Adjust the sending rate
}
// Clean up
DeleteObject(hBitmap);
DeleteDC(hMemDC);
ReleaseDC(NULL, hDC);
closesocket(clientSocket);
WSACleanup();
return 0;
}
std::vector<int> getxy() {
HWND hWnd = GetDesktopWindow();//根据需要可以替换成自己程序的句柄
HMONITOR hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
DEVMODE dm;
MONITORINFOEX miex;
dm.dmSize = sizeof(dm);
dm.dmDriverExtra = 0;
miex.cbSize = sizeof(miex);
GetMonitorInfo(hMonitor, &miex);
// 获取监视器物理宽度与高度
EnumDisplaySettings(miex.szDevice, ENUM_CURRENT_SETTINGS, &dm);
int cxPhysical = dm.dmPelsWidth;
int cyPhysical = dm.dmPelsHeight;
vector<int> ret;
ret.push_back(cxPhysical);
ret.push_back(cyPhysical);
return ret;
}
效果展示
API简介
WSAStartup
int WSAAPI WSAStartup(
[in] WORD wVersionRequested,
[out] LPWSADATA lpWSAData
);
wsastartup
- 初始化 Winsock 库:加载并初始化 Winsock 库的必要组件。
- 版本检查:应用程序可以通过
WSAStartup
指定所需的 Winsock 版本,同时函数会返回实际初始化的版本信息。 - 资源分配:为应用程序的网络操作分配必要的资源。
调用 WSAStartup
成功后,应用程序才能继续进行网络编程。当应用程序完成所有网络操作后,应调用 WSACleanup
函数来释放资源并终止 Winsock 使用。
inet_pton/inet_ntop
这两个函数是随IPv6出现的函数,对于IPv4地址和IPv6地址都适用,函数中p和n分别代表表达(presentation)和数值(numeric)。地址的表达格式通常是ASCII字符串,数值格式则是存放到套接字地址结构的二进制值。
int inet_pton(int family, const char *strptr, void *addrptr);
const char * inet_ntop(int family, const void *addrptr, char *strptr, size_t len);
StretchBlt /BitBlt/StretchDIBits
StretchBlt
和 BitBlt
是 Windows GDI(图形设备接口)中的两个函数,用于在设备上下文(Device Context,DC)之间进行位图的复制和绘制操作。它们的主要区别在于是否进行图像的缩放。StretchDIBits
从 DIB 数据(通常存储在内存中)到设备上下文进行更灵活的图像处理
调试代码
屏幕截屏
#include<stdio.h>
#include<windows.h>
#include<string>
#include<iostream>
using namespace std;
int main(void)
{
BITMAPFILEHEADER bfHeader;
BITMAPINFOHEADER biHeader;
BITMAPINFO bInfo;
HGDIOBJ hTempBitmap;
HBITMAP hBitmap;
BITMAP bAllDesktops;
HDC hDC, hMemDC;
LONG lWidth, lHeight;
BYTE* bBits = NULL;
HANDLE hHeap = GetProcessHeap();
DWORD cbBits, dwWritten = 0;
HANDLE hFile;
INT x = GetSystemMetrics(SM_XVIRTUALSCREEN);
INT y = GetSystemMetrics(SM_YVIRTUALSCREEN);
ZeroMemory(&bfHeader, sizeof(BITMAPFILEHEADER));
ZeroMemory(&biHeader, sizeof(BITMAPINFOHEADER));
ZeroMemory(&bInfo, sizeof(BITMAPINFO));
ZeroMemory(&bAllDesktops, sizeof(BITMAP));
hDC = GetDC(NULL);
hTempBitmap = GetCurrentObject(hDC, OBJ_BITMAP);
GetObjectW(hTempBitmap, sizeof(BITMAP), &bAllDesktops);
lWidth = bAllDesktops.bmWidth;
lHeight = bAllDesktops.bmHeight;
//get lWidth lHeight
DeleteObject(hTempBitmap);
bfHeader.bfType = (WORD)('B' | ('M' << 8));//小端存储BM
bfHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
biHeader.biSize = sizeof(BITMAPINFOHEADER);
biHeader.biBitCount = 24;
biHeader.biCompression = BI_RGB;
biHeader.biPlanes = 1;
biHeader.biWidth = lWidth;
biHeader.biHeight = lHeight;
bInfo.bmiHeader = biHeader;
cbBits = (((24 * lWidth + 31) & ~31) / 8) * lHeight;//~31 相当于将最低 5 位全置为 0,保证是32的倍数(四字节对齐)
hMemDC = CreateCompatibleDC(hDC);
hBitmap = CreateDIBSection(hDC, &bInfo, DIB_RGB_COLORS, (VOID**)&bBits, NULL, 0);
SelectObject(hMemDC, hBitmap);
BitBlt(hMemDC, 0, 0, lWidth, lHeight, hDC, x, y, SRCCOPY);
string path = "D:\\c_project\\dlltest\\a.bmp";
hFile = CreateFileA(path.c_str(), GENERIC_WRITE | GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
DeleteDC(hMemDC);
ReleaseDC(NULL, hDC);
DeleteObject(hBitmap);
return FALSE;
}
WriteFile(hFile, &bfHeader, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
WriteFile(hFile, &biHeader, sizeof(BITMAPINFOHEADER), &dwWritten, NULL);
WriteFile(hFile, bBits, cbBits, &dwWritten, NULL);
FlushFileBuffers(hFile);
CloseHandle(hFile);
DeleteDC(hMemDC);
ReleaseDC(NULL, hDC);
DeleteObject(hBitmap);
return TRUE;
}
保存的时刻为代码运行到BitBlt时刻的图像
本地实时渲染
#include <windows.h>
#include <stdio.h>
#include <string>
#include <iostream>
#include<vector>
using namespace std;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
std::vector<int> getxy();
int main(void)
{
// Register window class
WNDCLASS wc = { 0 };
wc.lpfnWndProc = WndProc;
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = L"ScreenCaptureWindowClass";
RegisterClass(&wc);
// Get screen dimensions
vector<int> xy = getxy();
int screenWidth = xy[0];
int screenHeight = xy[1];
// Define the desired window size (e.g., 800x600)
INT windowWidth = 800;
INT windowHeight = 600;
// Calculate aspect ratios
float screenAspect = (float)screenWidth / screenHeight;
float windowAspect = (float)windowWidth / windowHeight;
// Adjust window size to maintain the screen aspect ratio
if (screenAspect > windowAspect)
{
windowHeight = (INT)(windowWidth / screenAspect);
}
else
{
windowWidth = (INT)(windowHeight * screenAspect);
}
// Calculate window size including borders and title bar
RECT rect = { 0, 0, windowWidth, windowHeight };
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
// Create window
HWND hwnd = CreateWindowEx(0, wc.lpszClassName, L"Screen Capture", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, wc.hInstance, NULL);
ShowWindow(hwnd, SW_SHOW);
// Set up the screen capture
BITMAPINFO bInfo;
HDC hDC, hMemDC;
HBITMAP hBitmap;
BYTE* bBits = NULL;
hDC = GetDC(NULL);
hMemDC = CreateCompatibleDC(hDC);
ZeroMemory(&bInfo, sizeof(BITMAPINFO));
bInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bInfo.bmiHeader.biBitCount = 24;
bInfo.bmiHeader.biCompression = BI_RGB;
bInfo.bmiHeader.biPlanes = 1;
bInfo.bmiHeader.biWidth = screenWidth;
bInfo.bmiHeader.biHeight = -screenHeight; // Negative height to indicate top-down DIB
hBitmap = CreateDIBSection(hDC, &bInfo, DIB_RGB_COLORS, (VOID**)&bBits, NULL, 0);
SelectObject(hMemDC, hBitmap);
// Main message loop
MSG msg = { 0 };
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
// Capture the screen
BitBlt(hMemDC, 0, 0, screenWidth, screenHeight, hDC, 0, 0, SRCCOPY);
// Get the device context of the window
HDC hWindowDC = GetDC(hwnd);
// Scale and paint the captured screen to fit the window size
SetStretchBltMode(hWindowDC, HALFTONE);
StretchBlt(hWindowDC, 0, 0, windowWidth, windowHeight, hMemDC, 0, 0, screenWidth, screenHeight, SRCCOPY);
ReleaseDC(hwnd, hWindowDC);
// Sleep for 0.2 seconds (200 milliseconds)
//Sleep(200);
}
}
// Clean up
DeleteObject(hBitmap);
DeleteDC(hMemDC);
ReleaseDC(NULL, hDC);
return 0;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
std::vector<int> getxy() {
HWND hWnd = GetDesktopWindow();//根据需要可以替换成自己程序的句柄
HMONITOR hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
DEVMODE dm;
MONITORINFOEX miex;
dm.dmSize = sizeof(dm);
dm.dmDriverExtra = 0;
miex.cbSize = sizeof(miex);
GetMonitorInfo(hMonitor, &miex);
// 获取监视器物理宽度与高度
EnumDisplaySettings(miex.szDevice, ENUM_CURRENT_SETTINGS, &dm);
int cxPhysical = dm.dmPelsWidth;
int cyPhysical = dm.dmPelsHeight;
vector<int> ret;
ret.push_back(cxPhysical);
ret.push_back(cyPhysical);
return ret;
}
传输渲染
#include <windows.h>
#include <stdio.h>
#include <string>
#include <iostream>
#include<vector>
using namespace std;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
std::vector<int> getxy();
int main(void)
{
// Register window class
WNDCLASS wc = { 0 };
wc.lpfnWndProc = WndProc;
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = L"ScreenCaptureWindowClass";
RegisterClass(&wc);
// Get screen dimensions
vector<int> xy = getxy();
int screenWidth = xy[0];
int screenHeight = xy[1];
// Define the desired window size (e.g., 800x600)
INT windowWidth = 800;
INT windowHeight = 600;
// Calculate aspect ratios
float screenAspect = (float)screenWidth / screenHeight;
float windowAspect = (float)windowWidth / windowHeight;
// Adjust window size to maintain the screen aspect ratio
if (screenAspect > windowAspect)
{
windowHeight = (INT)(windowWidth / screenAspect);
}
else
{
windowWidth = (INT)(windowHeight * screenAspect);
}
// Calculate window size including borders and title bar
RECT rect = { 0, 0, windowWidth, windowHeight };
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
// Create window
HWND hwnd = CreateWindowEx(0, wc.lpszClassName, L"Screen Capture", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, wc.hInstance, NULL);
ShowWindow(hwnd, SW_SHOW);
// Set up the screen capture
BITMAPINFO bInfo;
HDC hDC, hMemDC;
HBITMAP hBitmap;
BYTE* bBits = NULL;
hDC = GetDC(NULL);
hMemDC = CreateCompatibleDC(hDC);
ZeroMemory(&bInfo, sizeof(BITMAPINFO));
bInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bInfo.bmiHeader.biBitCount = 24;
bInfo.bmiHeader.biCompression = BI_RGB;
bInfo.bmiHeader.biPlanes = 1;
bInfo.bmiHeader.biWidth = screenWidth;
bInfo.bmiHeader.biHeight = -screenHeight; // Negative height to indicate top-down DIB
hBitmap = CreateDIBSection(hDC, &bInfo, DIB_RGB_COLORS, (VOID**)&bBits, NULL, 0);
SelectObject(hMemDC, hBitmap);
int len = screenWidth * screenHeight * 3;
// Allocate a buffer for storing the screen data
BYTE* screenBuffer = new BYTE[len]; // 24-bit color
// Main message loop
MSG msg = { 0 };
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
// Capture the screen into buffer
BitBlt(hMemDC, 0, 0, screenWidth, screenHeight, hDC, 0, 0, SRCCOPY);
memcpy(screenBuffer, bBits, len); // Copy screen data to buffer
// Get the device context of the window
HDC hWindowDC = GetDC(hwnd);
// Create a compatible bitmap from buffer data
HBITMAP hBufferBitmap = CreateCompatibleBitmap(hWindowDC, screenWidth, screenHeight);
HDC hBufferDC = CreateCompatibleDC(hWindowDC);
SelectObject(hBufferDC, hBufferBitmap);
// Copy buffer data into the bitmap
SetDIBits(hBufferDC, hBufferBitmap, 0, screenHeight, screenBuffer, &bInfo, DIB_RGB_COLORS);
// Scale and paint the buffered screen to fit the window size
SetStretchBltMode(hWindowDC, HALFTONE);
StretchBlt(hWindowDC, 0, 0, windowWidth, windowHeight, hBufferDC, 0, 0, screenWidth, screenHeight, SRCCOPY);
// Clean up
DeleteObject(hBufferBitmap);
DeleteDC(hBufferDC);
ReleaseDC(hwnd, hWindowDC);
// Sleep for 0.2 seconds (200 milliseconds)
Sleep(200);
}
}
// Clean up
delete[] screenBuffer;
DeleteObject(hBitmap);
DeleteDC(hMemDC);
ReleaseDC(NULL, hDC);
return 0;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
std::vector<int> getxy() {
HWND hWnd = GetDesktopWindow();//根据需要可以替换成自己程序的句柄
HMONITOR hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
DEVMODE dm;
MONITORINFOEX miex;
dm.dmSize = sizeof(dm);
dm.dmDriverExtra = 0;
miex.cbSize = sizeof(miex);
GetMonitorInfo(hMonitor, &miex);
// 获取监视器物理宽度与高度
EnumDisplaySettings(miex.szDevice, ENUM_CURRENT_SETTINGS, &dm);
int cxPhysical = dm.dmPelsWidth;
int cyPhysical = dm.dmPelsHeight;
vector<int> ret;
ret.push_back(cxPhysical);
ret.push_back(cyPhysical);
return ret;
}
参数传递
// 发送结构体
xy data;
data.x = 10;
data.y = 20;
send(clientSocket, (char *) & data, sizeof(data), 0);
//接受结构体
xy data;
recv(clientSocket, (char*) & data, sizeof(data), 0);
std::cout << "Received: x = " << data.x << ", y = " << data.y << std::endl;
后记
BitBlt (Bit Block Transfer)
BitBlt
函数用于从一个设备上下文复制一个位图区域到另一个设备上下文。它不进行任何缩放操作,原样复制位图。通常用于在同一尺寸的区域之间移动或绘制位图。
函数原型:
cpp复制代码BOOL BitBlt(
HDC hdcDest, // 目标设备上下文句柄
int nXDest, // 目标矩形左上角的 X 坐标
int nYDest, // 目标矩形左上角的 Y 坐标
int nWidth, // 目标矩形的宽度
int nHeight, // 目标矩形的高度
HDC hdcSrc, // 源设备上下文句柄
int nXSrc, // 源矩形左上角的 X 坐标
int nYSrc, // 源矩形左上角的 Y 坐标
DWORD dwRop // 光栅操作代码
);
主要特性:
- 复制图像:从源设备上下文复制图像到目标设备上下文,不进行缩放。
- 位块传输:按照指定的矩形区域进行传输。
应用场景:
- 同尺寸位图:适用于源和目标位图区域尺寸相同的情况下的快速复制操作。
- 简单绘制:用于简单的图像绘制、窗口背景绘制等。
StretchBlt (Stretch Bit Block Transfer)
StretchBlt
函数与 BitBlt
类似,但它可以在复制位图时进行缩放。目标区域和源区域的大小可以不同,StretchBlt
会自动调整图像的尺寸,使之适应目标矩形。
函数原型:
cpp复制代码BOOL StretchBlt(
HDC hdcDest, // 目标设备上下文句柄
int nXOriginDest,// 目标矩形左上角的 X 坐标
int nYOriginDest,// 目标矩形左上角的 Y 坐标
int nWidthDest, // 目标矩形的宽度
int nHeightDest, // 目标矩形的高度
HDC hdcSrc, // 源设备上下文句柄
int nXOriginSrc, // 源矩形左上角的 X 坐标
int nYOriginSrc, // 源矩形左上角的 Y 坐标
int nWidthSrc, // 源矩形的宽度
int nHeightSrc, // 源矩形的高度
DWORD dwRop // 光栅操作代码
);
主要特性:
- 缩放图像:支持对位图进行缩放,目标区域可以比源区域大或小。
- 比例变换:自动调整图像比例,使其适应目标区域。
应用场景:
- 图像缩放:用于在图像渲染时需要缩放、拉伸或压缩的场景,如缩略图显示、窗口大小变化时的图像调整等。
- 动态布局:在需要根据设备上下文的大小动态调整图像显示时,
StretchBlt
是合适的选择。
总结
BitBlt
:直接复制图像,不进行缩放,适合源和目标区域大小一致的情况下。StretchBlt
:支持缩放,在复制图像时根据需要调整尺寸,适合在不同大小区域之间传输图像的场景。
字符转化
class Char {
public:
static std::wstring AtoW(const std::string& str)
{
int wcLen = MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0);
std::wstring newBuf;
newBuf.resize(wcLen);
MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, (LPWSTR)newBuf.c_str(), wcLen);
return newBuf;
}
static std::string WtoA(const std::wstring& str)
{
int cLen = WideCharToMultiByte(CP_ACP, 0, str.c_str(), -1, NULL, 0, 0, NULL);
std::string newBuf;
newBuf.resize(cLen);
WideCharToMultiByte(CP_ACP, 0, str.c_str(), -1, (char*)newBuf.c_str(), cLen, 0, NULL);
return newBuf;
}
};
reference
https://geocld.github.io/2021/03/02/bmp/