C++ С;从HDC创建位图

C++ С;从HDC创建位图,c++,winapi,C++,Winapi,问题是,虽然创建了图像,但左侧有一个小缩进,并附加了一个屏幕截图(顶部是我的程序生成的图像,就在程序本身的下方)。 HDC-hdcWindow{HdcWindowScreen},hdcMemDC{CreateCompatibleDC(hdcWindow)}; HBITMAP hbmScreen{}; 位图bmpScreen{}; RECT-rcClient; GetClientRect(WindowFromDC(hdcWindow)和rcClient); hbmScreen=CreateCom

问题是,虽然创建了图像,但左侧有一个小缩进,并附加了一个屏幕截图(顶部是我的程序生成的图像,就在程序本身的下方)。

HDC-hdcWindow{HdcWindowScreen},hdcMemDC{CreateCompatibleDC(hdcWindow)};
HBITMAP hbmScreen{};
位图bmpScreen{};
RECT-rcClient;
GetClientRect(WindowFromDC(hdcWindow)和rcClient);
hbmScreen=CreateCompatibleBitmap(hdcWindow,rcClient.right+rcClient.left,rcClient.bottom+rcClient.top);
选择对象(hdcMemDC、hbmScreen);
if(!(BitBlt(hdcMemDC,0,0,rcClient.right-rcClient.left,rcClient.bottom-rcClient.top,hdcWindow,0,0,SRCCOPY))){
消息框(hWnd,L“BitBlt已失败”,L“失败”,MB_OK);
ClearMemory();
}
GetObject(hdcWindow、sizeof(位图)和bmpScreen);
BITMAPFILEHEADER bmfHeader{};
BitMapInfo头bi{};
bi.biSize=sizeof(BITMAPFILEHEADER);
bi.biWidth=bmpScreen.bmWidth;
bi.biHeight=bmpScreen.bmHeight;
双平面=1;
bi.biBitCount=32;;
bi.biCompression=bi_RGB;
bi.biSizeImage=0;
bi.biXPelsPerMeter=0;
bi.biYPelsPerMeter=0;
bi.BICLRUSE=0;
bi.biclr=0;
DWORD dwBmpSize=((bmpScreen.bmWidth*bi.bibibitcount+31)/32)*4*bmpScreen.bmHeight;
DWORD dwSizeofDIB=dwBmpSize+sizeof(位图文件头)+sizeof(位图文件头);
bmfHeader.bfOffBits=静态_转换(sizeof(BITMAPFILEHEADER)+sizeof(BitMapInfo头));
bmfHeader.bfSize=dwSizeofDIB;
bmfHeader.bfType=0x4D42;
GdiplusStartupInput GdiplusStartupInput{};
ULONG_PTR gdiplusToken{};
Gdiplus::GdiplusStartup(&gdiplusToken,&gdiplusStartupInput,NULL);
CLSID myClsId{};
位图*图像=新位图(hbmScreen,nullptr);
图像->保存(文件名,&myClsId,NULL);
Gdiplus::GdiplusShutdown(gdiplusToken);
不包括边框和标题栏。全部 是否告诉您客户区的尺寸

检索边框的尺寸 指定窗口的。尺寸在屏幕上给出 相对于屏幕左上角的坐标

但Windows10在左、右和底部都有薄薄的不可见边框,用于抓握鼠标调整大小。边界可能如下所示:7,0,7,7(左、上、右、下)

所以,如果我们使用
GetWindowRect
,与我们在屏幕上看到的相比,这会给出一个稍大的窗口rect

请参阅:

正如@zett42所说,使用
DwmGetWindowAttribute
DWMWA\u EXTENDED\u FRAME\u BOUNDS
获得正确的窗口大小是一个好方法

像这样:

Rect rect;

DwmGetWindowAttribute(hWnd, DWMWA_EXTENDED_FRAME_BOUNDS, (PVOID)&rect, sizeof(rect));
注意:如果DPI发生更改,
GetWindowRect
将不会返回正确的窗口大小

但是
DwmGetWindowAttribute
仍将返回正确的大小

请参阅:

展开:如果DPI发生变化,
LogicalPhysicalPointforPermonitorDPI
可以返回正确的坐标(+不可见边框)

:将窗口中的点从逻辑坐标转换为物理坐标,而不考虑调用方的每英寸点数(dpi)


如果您认为使用不可见边框更好,那么可以使用此API。

rcClient的内容是什么??请尝试使用
GetWindowRect()
而不是
GetClientRect()
。窗口的客户端区域矩形通常比其整体窗口矩形小。
GetWindowRect()
也不能提供正确的大小,因为它包含阴影区域。使用
DwmGetWindowAttribute()
DWMWA\u EXTENDED\u FRAME\u BOUNDS
获得“真实”窗口大小。@Gogogo-Hi,答案对您有用吗?如果它对您有帮助,请标记它,这对社区的其他成员阅读此线程很有好处:)如果您不知道如何标记,请参阅
Rect rect;

DwmGetWindowAttribute(hWnd, DWMWA_EXTENDED_FRAME_BOUNDS, (PVOID)&rect, sizeof(rect));